Dites-moi au moins ce que vous pensez de l'idée...
J'ai oublié de préciser que la ligne de prise de bénéfices peut être supprimée si elle n'est pas nécessaire.
Le type d'ordre est choisi en fonction de l'emplacement de l'ouvreur et du stoploss...
Quant à ceux qui critiquent la mise en œuvre, je ne sais pas pourquoi ils disent qu'elle est "grossière".
Je suis sûr que de nombreuses personnes trouveront votre script très pratique à utiliser pour passer des commandes en attente.
Pour ceux qui aiment trader à partir du marché, j'ai proposé la version du script qui achète au prix actuel du marché avec calcul automatique de la taille du lot sur la base d'un stop loss placé dans Forex Magazine (voir l'article "Bibliothèques de fonctions et leur utilisation dans les programmes", numéro 52, 24 janvier 2005). À l'époque, il était impossible d'obtenir le prix auquel le script était "abaissé" sur le graphique dans MQL4, de sorte que le prix dans le script est toujours le même que sur le marché.
Le même programme peut être facilement modifié pour ouvrir, par exemple, un minilot avec un arrêt permanent. Et cette astuce de MessageBox va certainement me permettre d'ajouter des fonctionnalités à mon script également.
//+------------------------------------------------------------------+ //| 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); }
, j'ai en quelque sorte un comportement inadéquat de la fonction Lowest et ArrayMinimum sur le graphique EURUSD_H1
Le fait est qu'il semble que le minimum devrait coïncider avec la valeur de vendredi dernier, mais cela ne se produit pas et je renvoie le minimum de deux jours comme minimum.
Le code ci-dessus, avant que le tableau ne change, veuillez vérifier (c'est-à-dire avant dimanche soir).
Peut-être que je fais quelque chose de mal ?
l'implémentation est vraiment grossière :) j'écris ce script depuis une heure et demie.....
Je l'ai proposé comme une idée, si vous l'aimez, vous devrez l'affiner...
corne 06.02.05 06:45
merci pour le respect ;) et l'opportunité est vraiment marine - il faut la chercher !
rty : si quelqu'un sait comment faire un message "au dessus de toutes les fenêtres", dites-le moi, svp.... c'est tellement incroyable.....
pour automatiser les opérations de routine.
Voici une version sérieusement corrigée et fonctionnelle du script de placement d'ordre visuel :
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Ce qui est réparé :
1) tous les paramètres de Lowest(Symbol(),PERIOD_D1,MODE_LOW,DAYS_TO_CONSIDER,0) sont spécifiés,
il semble que l'erreur de Horn était que la valeur par défaut n'était pas définie. nous allons vérifier comment la fonction Lowest est appelée et fonctionne
2) NormalizeDouble - c'est très important !
3) Vérification préalable de l'exactitude des niveaux d'arrêt avant l'envoi des ordres.
4) le trader reçoit plus d'informations dans les fenêtres (dans la première version du script, il était très difficile de comprendre ce que faisait le script sans lire le code).
5) sortie détaillée et en temps voulu des journaux
6) commentaires ajoutés
7) la tentative cyclique d'envoyer une demande a été supprimée - elle est très importante.
Malheureusement, l'utilisation d'algorithmes en boucle comme :
while(true) { if(OrderSend(....)<=0) { // проверимся Sleep(10000); } }
est absolument contre-indiquée, voire interdite.
Laissez-moi essayer d'expliquer grossièrement la raison :
Si vous attrapez une erreur, vous ne serez de toute façon pas en mesure de traiter tous les types d'erreurs par vous-même. Il est trop probable que vous attrapiez cinq erreurs populaires environ et que vous fassiez quelque chose à leur sujet, mais que vous répétiez les opérations pour tout le reste. Et Sleep(10000) ne servira pas d'excuse au script pour envoyer des requêtes incorrectes. Les courtiers vont simplement bloquer le compte.
Comment doit procéder l'auteur d'un Expert Advisor :
1) Préparer un ordre
a) vérifier l'exactitude des paramètres d'entrée de l'Expert Advisor
b) normaliser indépendamment tous les prix et volumes (oui, ceux-là aussi !)) de la demande
c) vérifier indépendamment tous les champs de la demande pour éviter les erreurs stupides, au moins - pour que tous les prix soient plus ou moins corrects
d) avant d'envoyer la demande, afficher les détails de la demande dans le journal
2) organiser le cycle d'envoi de la demande
a) le cycle doit être fini, par exemple pas plus de 3 fois for(i=0;i<3;i++) et en aucun cas while(true)
b) si la demande passe, tout est facile sortie dans le journal, notification au négociant et sortie
c) erreur détectée, alors point 3
3) traitement des erreurs d'envoi d'ordre
a) vérifier les situations où nous pouvons récupérer, et pour toute autre erreur - sortie avec notifications dès que possible
b) cas de récupération choisir le moins possible, seulement le plus important et potentiellement récupérable
c) pas de tentatives de "pousser à travers" votre ordre répété en pensant "peut-être qu'ils vont accepter après tout ?"
d) comptabilisation obligatoire du slippage, au moins 1 point (soyez honnête avec vous-même, le slippage est inévitable dans le trading réel)
L'un des principaux points de l'utilisation de l'exécution des ordres à partir de MQL4 - minimiser le nombre d'ordres.
Cela affecte directement la qualité de votre service.
De même, pour les experts écrivant pour le public, vous devez écrire le code le plus infaillible.
Et pour un usage interne également.
J'ai utilisé MB_TOPMOST, essayez-le, il semble fonctionner pour moi.
- Applications de trading gratuites
- Plus de 8 000 signaux à copier
- Actualités économiques pour explorer les marchés financiers
Vous acceptez la politique du site Web et les conditions d'utilisation
Hier, je m'en suis souvenu et j'ai pensé : pourquoi ne pas le mettre en œuvre ?
19.03.2005
Lisez les instructions avant de l'utiliser =)
Si quelqu'un a des idées, faites-le nous savoir et nous y réfléchirons.
Peut-être que nous pouvons faire un GUO nous-mêmes......... ;)