Uygulamayı eleştirenlere gelince, uygulamanın "ham" olduğunu söylerken neye göre hareket ettikleri tam olarak belli değil.
Bekleyen siparişler vermek için birçok kişinin komut dosyanızla çalışmayı çok uygun bulacağından eminim.
Ve piyasadan girmeyi sevenler için, Forex Dergisi sayfalarında zaten önerdim ("İşlev kitaplıkları ve programlarda kullanımları" 24 Ocak 2005 52. sayısı) mevcut piyasa fiyatından satın alan bir komut dosyası seçeneği ayarlanmış durdurma kaybı temelinde boyut partilerinin otomatik hesaplanması ile. O zaman MQL4'te senaryonun grafikte "düştüğü" fiyatı almak henüz mümkün değildi ve bu nedenle içindeki fiyat her zaman piyasadaki fiyattır.
Aynı program, örneğin sabit bir durma ile bir mini-lot ile açılacak şekilde kolayca değiştirilebilir. Ancak MessageBox ile yapılan bu numara, kesinlikle betiğime işlevsellik eklememe izin verecek.
//+------------------------------------------------------------------+ //| 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); }
Lowest ve ArrayMinimum işlevleri EURUSD_H1 grafiğinde bir şekilde yetersiz davranıyor
Gerçek şu ki, görünüşe göre, minimum, son Cuma değeriyle çakışmalı, ancak bu olmuyor ve minimum olarak iki günlük bir minimum döndürüyorum.
Kod yukarıdadır, program değişmemişse lütfen kontrol edin (yani Pazar gecesine kadar).
Belki yanlış bir şey yapıyorum?
uygulama gerçekten ham :) Bu scripti bir buçuk saat yazdım .....
Bir fikir olarak önerdim, beğenirseniz düzeltmeniz gerekir...
Korna 06.02.05 06:45
saygınız için teşekkürler ;) ve gerçekten bir fırsatlar denizi var - onu aramanız gerekiyor!
Not: "tüm pencerelerin üstünde" nasıl mesaj yazılacağını bilen biri varsa, söyle bana, lütfen .... aksi halde çok rahatsız edici .....
rutin işlemleri otomatikleştirmek için.
İşte görsel olarak sipariş vermek için komut dosyasının ciddi şekilde düzeltilmiş ve çalışan bir versiyonu:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Neler düzeltildi:
1) tüm parametreler Lowest(Symbol(),PERIOD_D1,MODE_LOW,DAYS_TO_CONSIDER,0) içinde belirtilir,
Görünüşe göre Horn'un hatası varsayılan bir değer olmamasıydı. En Düşük işlevin çağrısını ve çalışmasını kontrol edeceğiz
2) NormalizeDouble aracılığıyla kullanılmış fiyatların normalleştirilmesi - bu çok önemli!
3) siparişlere göndermeden önce doğruluk için durma seviyelerinin ön kontrolleri
4) tüccara pencerelerde daha fazla bilgi verilir (betiğin ilk versiyonunda, kodu okumadan bu betiğin ne yaptığını anlamak çok zordu)
5) günlüklerin ayrıntılı ve zamanında çıktısı
6) eklenen yorumlar
7) döngüsel bir uygulama gönderme girişimi kaldırıldı - bu çok önemli .
Ne yazık ki, formun döngülü algoritmalarının kullanımı:
while(true) { if(OrderSend(....)<=0) { // проверимся Sleep(10000); } }
kesinlikle kontrendikedir, hatta yasaktır.
Nedenini kabaca açıklamaya çalışacağım:
Bir hata yakalarsanız, yine de tüm hata türlerini kendi başınıza halledemezsiniz. Yaklaşık beş popüler hatayı yakalamanız, onlar için bir şeyler yapmanız çok olasıdır, ancak yine de _ tüm diğer_ hatalar için işlemleri tekrar edeceksiniz. Ve hiçbir Sleep(10000), betiğin geçersiz istekler göndermesi için bir mazeret teşkil etmeyecektir. Aracılar sadece hesabı bloke eder.
Uzman yazar olarak nasıl davranılır:
1) başvurunun hazırlanma aşaması
a) uzmanın giriş parametrelerinin doğruluğunu kontrol edin
b) uygulamanın tüm fiyatlarını ve hacimlerini (evet, onlar da!) bağımsız olarak normalleştirin
c) Uygulamanın tüm alanlarını en azından en aptalca hatalar için bağımsız olarak kontrol edin - böylece tüm fiyatlar aşağı yukarı doğru olur
d) Başvuruyu göndermeden önce, günlükte uygulamanın ayrıntılarını görüntüleyin
2) uygulama gönderme döngüsünün organizasyonu
a) döngü sonlu olmalıdır, örneğin, for(i=0;i<3;i++) için en fazla 3 kez ve hiçbir durumda while(true)
b) emir geçtiyse, o zaman her şey kolaydır: onu günlüğe çıkarırız, tüccarı bilgilendiririz ve çıkarız
c) bir hata yakaladı, ardından 3. paragraf
3) başvuruları gönderirken hataları ele alma
a) Kurtulabileceğimiz durumları kontrol ederiz ve başka herhangi bir hata için en kısa sürede bildirimlerle çıkarız.
b) mümkün olduğunca az kurtarma vakası seçiyoruz, sadece en önemli ve potansiyel olarak kurtarılabilir
c) "Belki yine de kabul ederler?" düşüncesiyle yeniden başvurularını "zorlama" girişiminde bulunulmaz.
d) zorunlu kayma muhasebesi, en az 1 puan (kendinize karşı dürüst olun, gerçek ticarette kayma kaçınılmazdır)
MQL4'ten sipariş yürütmeyi kullanmanın ana noktalarından biri, sipariş sayısını en aza indirmektir.
Bu, hizmetinizin kalitesini doğrudan etkiler.
Ayrıca, halka yazan uzmanlar için en güvenli, hatasız kodu yazmak gerekir.
Evet ve dahili kullanım için - çok.
MB_TOPMOST kullandım, deneyin, başarmış gibiyim.
- Ücretsiz alım-satım uygulamaları
- İşlem kopyalama için 8.000'den fazla sinyal
- Finansal piyasaları keşfetmek için ekonomik haberler
Gizlilik ve Veri Koruma Politikasını ve MQL5.com Kullanım Şartlarını kabul edersiniz
Dün hatırladım, düşündüm - neden uygulamıyorsunuz?
19.03.2005 tarihli baskı
Lütfen kullanmadan önce talimatları okuyun =)
Herhangi birinin herhangi bir fikri varsa - söyle, düşüneceğiz.
Belki GDO'yu kendi başımıza yaparız .........;)