Sagen Sie mir wenigstens, was Sie von der Idee halten...
Ich vergaß zu erwähnen, dass die Gewinnmitnahmezeile gelöscht werden kann, wenn sie nicht benötigt wird.
Die Art der Order wird je nach Lage des Eröffners und des Stoploss gewählt...
Was die Kritiker der Umsetzung betrifft, so weiß ich nicht, warum sie sagen, sie sei "grob".
Ich bin mir sicher, dass viele Leute Ihr Skript sehr praktisch finden werden, um ausstehende Bestellungen aufzugeben.
Für diejenigen, die gerne vom Markt aus handeln, habe ich die Version des Skripts angeboten, die zum aktuellen Marktpreis kauft, mit automatischer Berechnung der Losgröße auf der Grundlage eines im Forex Magazine platzierten Stop-Loss (siehe den Artikel "Bibliotheken von Funktionen und ihre Verwendung in Programmen", Ausgabe 52, 24. Januar 2005). Damals war es nicht möglich, den Preis, zu dem das Skript "abgesenkt" wurde, in MQL4 auf den Chart zu übertragen, so dass der Preis im Skript immer derselbe ist wie auf dem Markt.
Dasselbe Programm kann leicht geändert werden, um z. B. einen Minilot mit einem permanenten Stopp zu öffnen. Und dieser MessageBox-Trick wird es mir auf jeden Fall ermöglichen, meinem Skript weitere Funktionen hinzuzufügen.
//+------------------------------------------------------------------+ //| 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); }
Ich habe irgendwie unangemessenes Verhalten von Lowest und ArrayMinimum Funktion auf EURUSD_H1 Chart
Der Punkt ist, dass es scheint, dass Minimum sollte mit dem Wert des letzten Freitag zusammenfallen, aber es passiert nicht und ich gebe zwei Tage Minimum als Minimum.
Bitte überprüfen Sie den obigen Code, bevor sich die Tabelle ändert (d.h. vor Sonntagabend).
Vielleicht mache ich etwas falsch?
die Umsetzung ist wirklich grob :) ich habe dieses Skript für eine Stunde und eine Hälfte geschrieben.....
Ich habe es als Idee vorgeschlagen, wenn es Ihnen gefällt, müssen Sie es verfeinern...
Horn 06.02.05 06:45
Danke für den Respekt ;) und die Gelegenheit ist wirklich meer - man muss sie nur suchen!
rty: Wenn jemand weiß, wie man eine Nachricht "über allen Fenstern" erstellt, sagen Sie es mir, plz.... es ist so unscheinbar.....
um Routinevorgänge zu automatisieren.
Hier ist eine stark korrigierte und funktionierende Version des Skripts für die visuelle Auftragserteilung:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Was ist repariert:
1) alle Parameter in Lowest(Symbol(),PERIOD_D1,MODE_LOW,DAYS_TO_CONSIDER,0) sind angegeben,
Es sieht so aus, als ob der Fehler von Horn darin bestand, dass der Standardwert nicht gesetzt wurde. Wir werden prüfen, wie die Funktion Lowest aufgerufen wird und funktioniert
2) NormalizeDouble - dies ist sehr wichtig!
3) Vorabprüfung der Stop-Levels auf Korrektheit, bevor sie an Aufträge gesendet werden
4) der Händler erhält mehr Informationen in den Fenstern (in der ersten Version des Skripts war es sehr schwierig zu verstehen, was das Skript tut, ohne den Code zu lesen)
5) detaillierte und zeitnahe Ausgabe von Protokollen
6) Kommentare hinzugefügt
7) Der zyklische Versuch, eine Anfrage zu senden, wurde entfernt - er ist sehr wichtig.
Leider ist die Verwendung von Algorithmen mit Schleifen wie :
while(true) { if(OrderSend(....)<=0) { // проверимся Sleep(10000); } }
ist absolut kontraindiziert, ja sogar verboten.
Lassen Sie mich versuchen, den Grund dafür grob zu erklären:
Wenn Sie sich einen Fehler einfangen, werden Sie ohnehin nicht in der Lage sein, alle Arten von Fehlern selbst zu behandeln. Es ist zu wahrscheinlich, dass Sie fünf oder so populäre Fehler erkennen und etwas dagegen tun, aber für den Rest immer noch _Wiederholungen_ durchführen. Und Sleep(10000) wird nicht als Ausrede für das Skript dienen, falsche Anfragen zu senden. Die Broker werden das Konto einfach sperren.
Wie sollte ein Autor eines Expert Advisors vorgehen:
1) Eine Order vorbereiten
a) Eingabeparameter des Expert Advisors auf Korrektheit prüfen
b) Selbstständig alle Preise und Volumina normalisieren (ja, auch die!) der Anfrage
c) unabhängig alle Felder der Anfrage auf dumme Fehler überprüfen, zumindest so, dass alle Preise mehr oder weniger korrekt sind
d) vor dem Absenden der Anfrage die Details der Anfrage im Protokoll anzeigen
2) den Zyklus des Absendens der Anfrage organisieren
a) der Zyklus muss endlich sein, zum Beispiel nicht mehr als 3 mal for(i=0;i<3;i++) und auf keinen Fall while(true)
b) wenn die Anfrage durchgeht, dann ist alles einfach Ausgabe in das Protokoll, Benachrichtigung des Händlers und Beendigung
c) ein Fehler aufgetreten ist, dann Punkt 3
3) Umgang mit Fehlern bei der Auftragsübermittlung
a) die Situationen prüfen, in denen eine Wiederherstellung möglich ist, und bei allen anderen Fehlern so schnell wie möglich eine Beendigung mit Benachrichtigung vornehmen
b) so wenige Fälle der Wiederherstellung wie möglich auswählen, nur die wichtigsten und potenziell wiederherstellbaren
c) keine Versuche, Ihre wiederholte Bestellung "durchzudrücken", weil Sie denken, "vielleicht wird sie doch noch angenommen?"
d) obligatorische Schlupfabrechnung, mindestens 1 Punkt (seien Sie ehrlich zu sich selbst, Schlupf ist im realen Handel unvermeidlich)
Einer der wichtigsten Punkte bei der Verwendung der Auftragsausführung von MQL4 - Minimierung der Anzahl der Aufträge.
Dies wirkt sich unmittelbar auf die Qualität Ihrer Dienstleistung aus.
Auch für Experten, die für die Öffentlichkeit schreiben, müssen Sie den narrensichersten Code schreiben.
Und auch für den internen Gebrauch.
Ich habe MB_TOPMOST verwendet, versuchen Sie es, es scheint für mich zu funktionieren.
![MQL5 - Sprache von Handelsstrategien, eingebaut ins Kundenterminal MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.
Gestern erinnerte ich mich daran und dachte: Warum nicht umsetzen?
19.03.2005
Lesen Sie die Anleitung, bevor Sie es benutzen =)
Wenn jemand eine Idee hat, lassen Sie es uns wissen und wir werden darüber nachdenken.
Vielleicht können wir selbst eine GUO machen.........;)