Ao menos me diga o que você acha da idéia...
Esqueci de dizer: Take profit line pode ser apagado se não for necessário.
O tipo de pedido é escolhido dependendo da localização do abridor e do batente.
Quanto àqueles que criticam a implementação, não sei por que eles dizem que é "grosseiro".
Tenho certeza de que muitas pessoas acharão seu roteiro muito conveniente de usar para fazer pedidos pendentes.
Para aqueles que gostam de negociar no mercado, ofereci a versão do roteiro que compra ao preço atual de mercado com cálculo automático do tamanho do lote com base num stop loss colocado na Revista Forex (veja o artigo "Bibliotecas de funções e sua utilização em programas", edição 52, 24 de janeiro de 2005). Naquela época, era impossível obter o preço ao qual o roteiro era "baixado" para o gráfico na MQL4, portanto o preço no roteiro é sempre o mesmo que no mercado.
O mesmo programa pode ser facilmente modificado para abrir, digamos, um minilot com uma parada permanente. E este truque da MessageBox definitivamente me permitirá adicionar funcionalidade ao meu script também.
//+------------------------------------------------------------------+ //| 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); }
eu tenho de alguma forma um comportamento inadequado da função Lowest e ArrayMinimum no gráfico EURUSD_H1
O ponto é que aparentemente o mínimo deve coincidir com o valor da última sexta-feira, mas isso não acontece e eu fico com um mínimo de dois dias de baixa como mínimo.
O código acima, antes de mudar a tabela, favor verificar (isto é, antes da noite de domingo).
Talvez eu esteja fazendo algo errado?
a implementação é realmente grosseira :) estou escrevendo este roteiro há uma hora e meia.....
Eu a sugeri como uma idéia, se você gostar, precisará refiná-la...
buzina 06.02.05 06:45
obrigado pelo respeito ;) e a oportunidade é realmente marítima - você tem que procurá-la!
rty: se alguém sabe como fazer uma mensagem "em cima de todas as janelas", me diga, plz.... é tão pouco provável.....
para automatizar as operações rotineiras.
Aqui está uma versão seriamente corrigida e funcional do roteiro para a colocação de pedidos visuais:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
O que é fixo:
1) todos os parâmetros em Lowest(Symbol(),PERIOD_D1,MODE_LOW,DAYS_TO_CONSIDER,0) são especificados,
parece que o erro de Horn foi que o valor padrão não foi definido. vamos verificar como a função mais baixa é chamada e funciona
2) NormalizeDuplo - isto é muito importante!
3) Pré-verificação dos níveis de parada para a correção antes do envio aos pedidos
4) o comerciante recebe mais informações nas janelas (na primeira versão do roteiro sem ler o código era muito difícil de entender o que o roteiro faz)
5) saída detalhada e oportuna dos logs
6) comentários adicionados
7) a tentativa cíclica de enviar um pedido foi retirada - é muito importante.
Infelizmente, utilizando algoritmos em loop como :
while(true) { if(OrderSend(....)<=0) { // проверимся Sleep(10000); } }
é absolutamente contra-indicado, até mesmo proibido.
Deixe-me tentar explicar o motivo:
Se você pegar um erro, não será capaz de lidar com todos os tipos de erros sozinho de qualquer maneira. É muito provável que você pegue cinco ou mais erros populares e faça algo a respeito deles, mas ainda assim _repetir operações_ para todos os demais. E o Sleep(10000) não servirá como desculpa para o roteiro enviar pedidos incorretos. Os corretores simplesmente bloquearão a conta.
Como deve proceder um consultor especializado:
1) Prepare um pedido
a) verifique os parâmetros de entrada do consultor especializado para verificar a exatidão
b) normalize independentemente todos os preços e volumes (sim, esses também!) do pedido
c) verificar independentemente todos os campos do pedido por erros bobos, pelo menos - para que todos os preços estejam mais ou menos corretos
d) antes de enviar o pedido, exibir detalhes do pedido no log
2) organizar o ciclo de envio do pedido
a) o ciclo deve ser finito, por exemplo não mais de 3 vezes para(i=0;i<3;i++) e em nenhum caso enquanto(true)
b) se o pedido passar, então tudo é fácil saída para o log, notificar o trader e sair
c) pegou um erro, depois o ponto 3
3) tratamento de erros de envio de pedidos
a) verificar as situações em que podemos nos recuperar, e para qualquer outro erro - sair com notificações o mais rápido possível
b) casos de recuperação escolher o menor número possível, apenas o mais importante e potencialmente recuperável
c) nenhuma tentativa de "empurrar" seu pedido repetido pensando "talvez eles ainda aceitem?"
d) contabilidade obrigatória de deslizamento, pelo menos 1 ponto (seja honesto consigo mesmo, o deslizamento é inevitável em negociações reais)
Um dos principais pontos no uso da execução de ordens da MQL4 - minimizar o número de ordens.
Isto afeta diretamente a qualidade de seu serviço.
Além disso, para especialistas escrevendo para o público, você precisa escrever o código mais infalível.
E também para uso interno.
Eu usei MB_TOPMOST, experimente, parece funcionar para mim.
![MQL5 - Linguagem para estratégias de negociação inseridas no terminal do cliente MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso
Ontem eu me lembrei e pensei - por que não implementá-lo?
19.03.2005
Leia as instruções antes de utilizá-lo =)
Se alguém tiver alguma idéia, nos avise e pensaremos sobre isso.
Talvez possamos fazer uma GUO nós mesmos.........;)