Almeno dimmi cosa ne pensi dell'idea...
Ho dimenticato di dire: la linea di take profit può essere cancellata se non è necessaria.
Il tipo di ordine viene scelto a seconda della posizione dell'apertura e dello stoploss...
Per quanto riguarda coloro che criticano l'implementazione, non so perché dicono che è "rozzo".
Sono sicuro che molte persone troveranno il tuo script molto comodo da usare per piazzare ordini in sospeso.
Per coloro che amano fare trading dal mercato, ho offerto la versione dello script che compra al prezzo corrente di mercato con calcolo automatico della dimensione del lotto sulla base di uno stop loss collocato in Forex Magazine (vedi l'articolo "Librerie di funzioni e loro utilizzo nei programmi", numero 52, 24 gennaio 2005). A quel tempo, era impossibile ottenere il prezzo al quale lo script veniva "abbassato" sul grafico in MQL4, quindi il prezzo nello script è sempre lo stesso del mercato.
Lo stesso programma può essere facilmente modificato per aprire, diciamo, un minilotto con un arresto permanente. E questo trucco MessageBox mi permetterà sicuramente di aggiungere funzionalità anche al mio script.
//+------------------------------------------------------------------+ //| 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); }
ho in qualche modo un comportamento inadeguato della funzione Lowest e ArrayMinimum sul grafico EURUSD_H1
Il punto è che sembra che il minimo dovrebbe coincidere con il valore di venerdì scorso, ma non succede e restituisco come minimo due giorni.
Il codice di cui sopra, prima che il grafico cambi per favore controlla (cioè prima di domenica sera).
Forse sto facendo qualcosa di sbagliato?
l'implementazione è davvero grezza :) ho scritto questo script per un'ora e mezza.....
L'ho suggerito come idea, se ti piace, dovrai perfezionarlo...
corno 06.02.05 06:45
grazie per il rispetto ;) e l'opportunità è davvero mare - bisogna cercarla!
rty: se qualcuno sa come fare un messaggio "in cima a tutte le finestre", me lo dica, plz.... è così poco credibile.....
per automatizzare le operazioni di routine.
Ecco una versione seriamente corretta e funzionante dello script per il posizionamento visivo degli ordini:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Cosa c'è di fisso:
1) tutti i parametri in Lowest(Symbol(),PERIOD_D1,MODE_LOW,DAYS_TO_CONSIDER,0) sono specificati,
sembra che l'errore di Horn fosse che il valore predefinito non era impostato. controlleremo come la funzione Lowest è chiamata e funziona
2) NormalizeDouble - questo è molto importante!
3) Controllo preliminare dei livelli di stop per la correttezza prima dell'invio agli ordini
4) il trader riceve più informazioni nelle finestre (nella prima versione dello script senza leggere il codice era molto difficile capire cosa fa lo script)
5) uscita dettagliata e tempestiva dei registri
6) commenti aggiunti
7) il tentativo ciclico di inviare una richiesta è stato rimosso - è molto importante.
Sfortunatamente, usando algoritmi in loop come:
while(true) { if(OrderSend(....)<=0) { // проверимся Sleep(10000); } }
è assolutamente controindicato, addirittura proibito.
Lasciatemi provare a spiegare approssimativamente il motivo:
Se catturate un errore, non sarete comunque in grado di gestire tutti i tipi di errore da soli. È troppo probabile che si colgano cinque errori popolari e si faccia qualcosa a riguardo, ma che si continuino a _ripetere le operazioni_ per tutto il resto. E Sleep(10000) non servirà da scusa allo script per inviare richieste errate. I broker bloccheranno semplicemente il conto.
Come dovrebbe procedere un autore di Expert Advisor:
1) Preparare un ordine
a) controllare i parametri di input dell'Expert Advisor per la correttezza
b) normalizzare indipendentemente tutti i prezzi e i volumi (sì, anche quelli!) della richiesta
c) controllare indipendentemente tutti i campi della richiesta per errori stupidi, almeno - in modo che tutti i prezzi siano più o meno corretti
d) prima di inviare la richiesta, visualizzare i dettagli della richiesta nel log
2) organizzare il ciclo di invio della richiesta
a) il ciclo deve essere finito, per esempio non più di 3 volte for(i=0;i<3;i++) e in nessun caso while(true)
b) se la richiesta passa, allora tutto è facile uscita nel log, notifica al trader e uscita
c) preso un errore, allora punto 3
3) gestire gli errori di invio degli ordini
a) controllare le situazioni in cui possiamo recuperare, e per qualsiasi altro errore - uscire con le notifiche il più presto possibile
b) i casi di recupero scegliere il minor numero possibile, solo i più importanti e potenzialmente recuperabili
c) nessun tentativo di "spingere attraverso" il vostro ordine ripetuto pensando "forse accetteranno dopo tutto?"
d) contabilità obbligatoria dello slippage, almeno 1 punto (siate onesti con voi stessi, lo slippage è inevitabile nel trading reale)
Uno dei punti principali nell'uso dell'esecuzione degli ordini da MQL4 - minimizzare il numero di ordini.
Questo influisce direttamente sulla qualità del vostro servizio.
Inoltre, per gli esperti che scrivono per il pubblico, è necessario scrivere il codice più infallibile.
E anche per uso interno.
Ho usato MB_TOPMOST, provatelo, sembra funzionare per me.
- App di trading gratuite
- Oltre 8.000 segnali per il copy trading
- Notizie economiche per esplorare i mercati finanziari
Accetti la politica del sito e le condizioni d’uso
Ieri mi sono ricordato e ho pensato - perché non implementarlo?
19.03.2005
Leggere le istruzioni prima di usarlo =)
Se qualcuno ha qualche idea, ce lo faccia sapere e ci penseremo.
Forse possiamo fare una GUO noi stessi.........;)