Caros,
Criei um script de negociação automatizado, quando executo ele em conta demo funciona normal, mas quando executo na conta real para cada comando de BUY ou SELL é executado duas vezes.
Segue o código de Buy como exemplo:
Agradeço a ajuda.
Isoladamente, este trecho de código que vc postou com certeza só vai enviar a ordem 1 vez. O que deve estar acontecendo é que esse trecho está sendo executado mais de 1 vez. Teria que ver o restante do código pra entender por que.
Vc relata que isso acontece na conta real, mas não na conta demo. Isso já nos dá uma boa pista, pois talvez o problema esteja relacionado ao tempo que leva entre o envio da ordem por meio do comando OrderSend() e essa ordem ser recebida e confirmada pela bolsa e aparecer listada quando você consultar os dados do terminal usando OrdersTotal(), OrderSelect(), etc.
Na conta real, esse processo leva alguns centésimos ou décimos de segundo, enquanto que na conta demo esse processo será instantâneo, pois ele não envia de verdade a ordem pra bolsa, apenas altera o seu ambiente (OrdersTotal(), OrderSelect(), etc.) como se a ordem tivesse sido enviada.
Suponhamos, por exemplo, que no evento OnTick() vc tenha uma lógica que envia uma nova ordem sempre que OrdersTotal() for igual a zero. Nesse caso, poderia acontecer o seguinte na conta real: vc envia uma ordem num evento Ontick() e ela leva alguns décimos de segundo para ser registrada, de modo que, se um segundo evento OnTick() chegar nesse meio tempo, OrdersTotal() ainda estará retornando zero e nesse caso a lógica de processamento do evento Ontick() vai enviar a ordem pela segunda vez.
Já na conta demo isso não aconteceria, pois, como o servidor demo não envia as ordens de verdade, apenas atualiza o ambiente como se a ordem tivesse sido enviada, OrdersTotal() já passa a retornar 1 assim que o comando OrderSend() é executado, antes mesmo de sair do primeiro evento OnTick().
Não sei como é a sua lógica de processamento. Teria que ver o restante do seu código. Verifique se a lógica de processamento que você usa para enviar as ordens tem o tipo de vulnerabilidade que descrevi acima.
Olá Maronezzi,
muito estranho mesmo, tem um comando Sleep(5000) e a hora das mensagens do "SEND" estão no mesmo instante!
Tem também um "}" não indentado no trecho postado, esse trecho postado você alterou antes de enviar?
At.te
Rogério
Eu não tinha reparado o Sleep(5000). Muito estranho mesmo!!!
Isso derruba completamente a minha hipótese, pois, se o código estivesse sendo executado duas vezes seguidas, deveria haver uma distância de 5 segundos entre as 2 ordens.
@maronezzi, esse Sleep(5000) já estava inserido no código quando o problema aconteceu? Ou vc colocou depois?
Uma outra hipótese: será que você estava com 2 instâncias do mesmo robô operando simultaneamente no WINQ18 em 2 janelas distintas? Isso já aconteceu comigo (em conta demo, felizmente).
Vc consegue reproduzir o problema ?
Eu não tinha reparado o Sleep(5000). Muito estranho mesmo!!!
Isso derruba completamente a minha hipótese, pois, se o código estivesse sendo executado duas vezes seguidas, deveria haver uma distância de 5 segundos entre as 2 ordens.
@maronezzi, esse Sleep(5000) já estava inserido no código quando o problema aconteceu? Ou vc colocou depois?
Uma outra hipótese: será que você estava com 2 instâncias do mesmo robô operando simultaneamente no WINQ18 em 2 janelas distintas? Isso já aconteceu comigo (em conta demo, felizmente).
Vc consegue reproduzir o problema ?
@Rogerio Giannetti Torres e @Trader_Patinhas, obrigado pelas prontas respostas.
Respondendo as perguntas, esse código é o que esta rodando, o erro é repetido toda as vezes que entra a opção de Buy ou Sell, e quando executa o PositionClose() ele fecha abre e fecha as posições.
Eu postei a pergunta, porque mesmo com o Sleep(5000) o erro continua e o tempo da operação como vocês observaram não obedece ele.
O meu script roda em uma VPS, mas na primeira vez que rodei a latência estava bem baixa, na casa de 56ms. Também rodei o backtest com vários valores de latência, mas o erro não acontece.
Eu tenho rodado a conta rela da XP e uso as contas demo da Clear para os teste, portanto não vejo dois scprits rodando em paralelo.
Antes de rodar na conta Real, deixei por vários dias rodando em conta Demo, mas o erro não acontece.
Vou postar o código, mas não sou um programador muito experiente, portanto podem ter coisas que poderiam ser otimizadas, com o tempo vou corrigindo elas.
#include <Trade\Trade.mqh> CTrade trade; //+------------------------------------------------+ //| Declaration of constants | //+------------------------------------------------+ #define EXPERT_MAGIC_BUY 123456 // MagicNumber of the expert #define EXPERT_MAGIC_SELL 654321 // MagicNumber of the expert #define rates_total Bars(_Symbol, ENUM_TIMEFRAMES(_Period) ) input double volumeOp = 5; //+------------------------------------------------+ //---- declaration of the integer variables for the start of data calculation int min_rates_total; //---- declaration of a variable for storing the Fibo level double level; double high[],low[],open[],close[]; long tick_volume[], volume[]; datetime time[]; datetime timedest[]; //int rates_total; int prev_calculated; string compra, venda; double tp1,tp2,tp3; double NsLVend, NsLComp ; double candleOperadoStop = 0; //************************************************************************************************************* //************************************************************************************************************* //************************************************************************************************************* //************************************************************************************************************* //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum DATE_TYPE { DAILY, WEEKLY, MONTHLY }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum PRICE_TYPE { OPEN, CLOSE, HIGH, LOW, OPEN_CLOSE, HIGH_LOW, CLOSE_HIGH_LOW, OPEN_CLOSE_HIGH_LOW }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ datetime CreateDateTime(DATE_TYPE nReturnType=DAILY,datetime dtDay=D'2000.01.01 00:00:00',int pHour=0,int pMinute=0,int pSecond=0) { datetime dtReturnDate; MqlDateTime timeStruct; TimeToStruct(dtDay,timeStruct); timeStruct.hour = pHour; timeStruct.min = pMinute; timeStruct.sec = pSecond; dtReturnDate=(StructToTime(timeStruct)); if(nReturnType==WEEKLY) { while(timeStruct.day_of_week!=0) { dtReturnDate=(dtReturnDate-86400); TimeToStruct(dtReturnDate,timeStruct); } } if(nReturnType==MONTHLY) { timeStruct.day=1; dtReturnDate=(StructToTime(timeStruct)); } return dtReturnDate; } int OpenBuyOrder() { int total=OrdersTotal(); int count=0; ulong ticket; double open_price; double initial_volume; datetime time_setup; string symbol; string type; long order_magic; long positionID; for(uint i=0;i<total;i++) { //--- voltar ticket ordem por sua posição na lista if((ticket=OrderGetTicket(i))>0) { //--- retorna propriedades de uma Ordem open_price =OrderGetDouble(ORDER_PRICE_OPEN); time_setup =(datetime)OrderGetInteger(ORDER_TIME_SETUP); symbol =OrderGetString(ORDER_SYMBOL); order_magic =OrderGetInteger(ORDER_MAGIC); positionID =OrderGetInteger(ORDER_POSITION_ID); initial_volume=OrderGetDouble(ORDER_VOLUME_INITIAL); type =EnumToString(ENUM_ORDER_TYPE(OrderGetInteger(ORDER_TYPE))); if(order_magic==EXPERT_MAGIC_BUY) { count++; } } } return(count); } int OpenSellOrder() { int total=OrdersTotal(); int count=0; ulong ticket; double open_price; double initial_volume; datetime time_setup; string symbol; string type; long order_magic; long positionID; for(uint i=0;i<total;i++) { //--- voltar ticket ordem por sua posição na lista if((ticket=OrderGetTicket(i))>0) { //--- retorna propriedades de uma Ordem open_price =OrderGetDouble(ORDER_PRICE_OPEN); time_setup =(datetime)OrderGetInteger(ORDER_TIME_SETUP); symbol =OrderGetString(ORDER_SYMBOL); order_magic =OrderGetInteger(ORDER_MAGIC); positionID =OrderGetInteger(ORDER_POSITION_ID); initial_volume=OrderGetDouble(ORDER_VOLUME_INITIAL); type =EnumToString(ENUM_ORDER_TYPE(OrderGetInteger(ORDER_TYPE))); //--- preparar e apresentar informações sobre a ordem if(order_magic==EXPERT_MAGIC_SELL) { count++; } } } return(count); } void CloseAll() { CTrade trade; for (int i=PositionsTotal()-1;i>=0; i--) { { if(!trade.PositionClose(PositionGetSymbol(i),5)) { Print(PositionGetSymbol(i), "PositionClose() method failed. Return code=",trade.ResultRetcode(), ". Code description: ",trade.ResultRetcodeDescription()); } else { Print(PositionGetSymbol(i), "PositionClose() method executed successfully. Return code=",trade.ResultRetcode(), " (",trade.ResultRetcodeDescription(),")"); Sleep(5000); } } } } input PRICE_TYPE Price_Type = CLOSE_HIGH_LOW; input bool Enable_Daily = true; bool Show_Daily_Value = true; double VWAP_Buffer_Daily; double nPriceArr[]; double nTotalTPV[]; double nTotalVol[]; double nSumDailyTPV = 0, nSumWeeklyTPV = 0, nSumMonthlyTPV = 0; double nSumDailyVol = 0, nSumWeeklyVol = 0, nSumMonthlyVol = 0; int nIdxDaily=0,nIdxWeekly=0,nIdxMonthly=0,nIdx=0; bool bIsFirstRun=true; ENUM_TIMEFRAMES LastTimePeriod=PERIOD_MN1; string sDailyStr = ""; datetime dtLastDay=CreateDateTime(DAILY),dtLastWeek=CreateDateTime(WEEKLY),dtLastMonth=CreateDateTime(MONTHLY); input double tpMax = 100; input double tpMin = 100; input double imarap = 9; input double imalenta = 21; input double slcomprado = 1; input double slvendido = 1; input bool ordemcompra = true; input bool ordemvenda = true; input string horainicioOp = "11:00"; input string horafimOp = "15:00"; //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { double Bid=NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits); double Ask=NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits); MqlTradeRequest request={0}; MqlTradeResult result={0}; // Contador de Candles MqlRates priceData[]; ArraySetAsSeries(priceData, true); CopyRates(_Symbol, _Period, 0, 3, priceData); static int candleCounter; static int candleAnterior; static datetime timeStampLastCheck; datetime timeStampCurrentCandle; timeStampCurrentCandle = priceData[0].time; string dateStampCurrentCandle=TimeToString(timeStampCurrentCandle,TIME_DATE); static string dateStampLastCheck; if (timeStampCurrentCandle != timeStampLastCheck) { timeStampLastCheck = timeStampCurrentCandle; candleCounter = candleCounter + 1; if (dateStampCurrentCandle != dateStampLastCheck) { dateStampLastCheck = dateStampCurrentCandle; candleCounter = 0; } } //Entrada de valores CopyHigh(_Symbol,_Period,0,rates_total,high); CopyLow(_Symbol,_Period,0,rates_total,low); CopyOpen(_Symbol,_Period,0,rates_total,open); CopyClose(_Symbol,_Period,0,rates_total,close); CopyTime(_Symbol,_Period,0,rates_total,time); CopyTickVolume(_Symbol,_Period,0,rates_total ,tick_volume); CopyRealVolume(_Symbol,_Period,0,rates_total ,volume); prev_calculated = BarsCalculated(rates_total); //---- indexing elements in arrays as timeseries ArraySetAsSeries(high,false); ArraySetAsSeries(low,false); ArraySetAsSeries(open,false); ArraySetAsSeries(close,false); ArraySetAsSeries(time,false); ArraySetAsSeries(tick_volume,false); ArraySetAsSeries(volume,false); //---- declarations of local variables static uint buycount=0,sellcount=0; double maxHigh3,minLow3; int rates_total1 = rates_total; // invert o array low double lowinverse[]; int size = ArraySize(low); ArrayResize(lowinverse, size); for ( int i=0; i<size; i++ ) { lowinverse[size-i-1] = low[i]; } // invert o array low double highinverse[]; size = ArraySize(high); ArrayResize(highinverse, size); for ( int i=0; i<size; i++ ) { highinverse[size-i-1] = high[i]; } //************************************************************************************************************* //************************************************************************************************************* //************************************************************************************************************* //************************************************************************************************************* double mediamovelrap[], mediamovellenta[]; int mediamovelrapdef = iMA(_Symbol, _Period, imarap, 0, MODE_EMA, PRICE_CLOSE); int mediamovellentadef = iMA(_Symbol, _Period, imalenta, 0, MODE_SMA, PRICE_CLOSE); ArraySetAsSeries(mediamovelrap, true); ArraySetAsSeries(mediamovellenta, true); CopyBuffer(mediamovelrapdef, 0, 0, 3, mediamovelrap); CopyBuffer(mediamovellentadef, 0, 0, 3, mediamovellenta); if (candleCounter != candleAnterior) { if(PERIOD_CURRENT!=LastTimePeriod) { bIsFirstRun=true; LastTimePeriod=PERIOD_CURRENT; } if(rates_total!=prev_calculated || bIsFirstRun) { ArrayResize(nPriceArr,rates_total); ArrayResize(nTotalTPV,rates_total); ArrayResize(nTotalVol,rates_total); if(Enable_Daily) {nIdx = nIdxDaily; nSumDailyTPV = 0; nSumDailyVol = 0;} for(; nIdx<rates_total; nIdx++) { if(CreateDateTime(DAILY,time[nIdx])!=dtLastDay) { nIdxDaily=nIdx; nSumDailyTPV = 0; nSumDailyVol = 0; } nPriceArr[nIdx] = 0; nTotalTPV[nIdx] = 0; nTotalVol[nIdx] = 0; switch(Price_Type) { case OPEN_CLOSE_HIGH_LOW: nPriceArr[nIdx]=(open[nIdx]+close[nIdx]+high[nIdx]+low[nIdx])/4; break; default: nPriceArr[nIdx]=(close[nIdx]+high[nIdx]+low[nIdx])/3; break; } if(tick_volume[nIdx]) { nTotalTPV[nIdx] = (nPriceArr[nIdx] * tick_volume[nIdx]); nTotalVol[nIdx] = (double)tick_volume[nIdx]; } else if(volume[nIdx]) { nTotalTPV[nIdx] = (nPriceArr[nIdx] * volume[nIdx]); nTotalVol[nIdx] = (double)volume[nIdx]; } if(Enable_Daily && (nIdx>=nIdxDaily)) { nSumDailyTPV += nTotalTPV[nIdx]; nSumDailyVol += nTotalVol[nIdx]; if(nSumDailyVol) VWAP_Buffer_Daily=(nSumDailyTPV/nSumDailyVol); if((sDailyStr!="VWAP Daily: "+(string)NormalizeDouble(VWAP_Buffer_Daily,_Digits)) && Show_Daily_Value) { sDailyStr="VWAP Daily: "+(string)NormalizeDouble(VWAP_Buffer_Daily,_Digits); ObjectSetString(0,"VWAP_Diario",OBJPROP_TEXT,sDailyStr); } } dtLastDay=CreateDateTime(DAILY,time[nIdx]); } bIsFirstRun=false; } }
@Rogerio Giannetti Torres e @Trader_Patinhas, obrigado pelas prontas respostas.
Respondendo as perguntas, esse código é o que esta rodando, o erro é repetido toda as vezes que entra a opção de Buy ou Sell, e quando executa o PositionClose() ele fecha abre e fecha as posições.
Eu postei a pergunta, porque mesmo com o Sleep(5000) o erro continua e o tempo da operação como vocês observaram não obedece ele.
O meu script roda em uma VPS, mas na primeira vez que rodei a latência estava bem baixa, na casa de 56ms.
Eu tenho rodado a conta rela da XP e uso as contas demo da Clear para os teste, portanto não vejo dois scprits rodando em paralelo.
Antes de rodar na conta Real, deixei por vários dias rodando em conta Demo, mas o erro não acontece.
Vou postar o código, mas não sou um programador muito experiente, portanto podem ter coisas que poderiam ser otimizadas, com o tempo vou corrigindo elas.
//************************************************************************************************************* //************************************************************************************************************* //************************************************************************************************************* //************************************************************************************************************* //--- declare and initialize the trade request and result of trade request string horadata = TimeToString(TimeLocal(),TIME_MINUTES); //************************************************************************************************************* //************************************************************************************************************* int posicaoTotal = PositionsTotal(); static int candleOperado; /* */ //**************************************************************************************************************** //**************************************************************************************************************** if (ordemcompra == true) { //Exclui ordem de compra abaixo da MM e Vwap if (OrdersTotal() > 0 && candleAnterior != candleCounter && candleOperado != candleCounter && high[rates_total1-2] < VWAP_Buffer_Daily && high[rates_total1-2] < mediamovelrap[1] && Ask < high[rates_total1-2]) { for(int i=0; i<OrdersTotal(); i++) { ulong order_ticket=OrderGetTicket(i); // bilhete da ordem ulong magic=OrderGetInteger(ORDER_MAGIC); if(magic==EXPERT_MAGIC_BUY) { ZeroMemory(request); ZeroMemory(result); //--- setting the operation parameters request.action=TRADE_ACTION_REMOVE; // type of trade operation request.order = order_ticket; // order ticket //--- send the request if(!OrderSend(request,result)) PrintFormat("OrderSend error %d",GetLastError()); // if unable to send the request, output the error code //--- information about the operation PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order); Sleep(5000); ZeroMemory(request); ZeroMemory(result); candleOperado = candleCounter; } } } //Altera a ordem de compra if (high[rates_total1-2] <= high[rates_total1-3] && OrdersTotal() > 0 && candleAnterior != candleCounter && candleOperado != candleCounter) { //-- declaração e inicialização do pedido e o seu resultado //--- iterar todas as ordens pendentes colocadas for(int i=0; i<OrdersTotal(); i++) { //--- parâmetros da ordem ulong order_ticket=OrderGetTicket(i); // bilhete da ordem string order_symbol=Symbol(); // símbolo int digits=(int)SymbolInfoInteger(order_symbol,SYMBOL_DIGITS); // número de signos depois da coma ulong magic=OrderGetInteger(ORDER_MAGIC); // MagicNumber da ordem double volume=OrderGetDouble(ORDER_VOLUME_CURRENT); // volume atual da ordem double sl=OrderGetDouble(ORDER_SL); // Stop Loss atual da ordem double tp=OrderGetDouble(ORDER_TP); // Take Profit atual da ordem ENUM_ORDER_TYPE type=(ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE); // tipo de ordem double price; // preço de ativação da ordem double point=SymbolInfoDouble(order_symbol,SYMBOL_POINT); // tamanho do ponto if(magic==EXPERT_MAGIC_BUY) { MqlTradeRequest request={0}; MqlTradeResult result={0}; double SL_buy = lowinverse[ArrayMinimum(lowinverse,1,slcomprado)]; price = high[rates_total1-2]; // price for opening price = NormalizeDouble(price/5,0) * 5; request.type_filling = ORDER_FILLING_RETURN; request.expiration = ORDER_TIME_GTC; request.action=TRADE_ACTION_MODIFY; // tipo de operação de negociação request.order = OrderGetTicket(i); // bilhete da ordem request.symbol =Symbol(); // símbolo //--- definição do nível de preços Take Profit e Stop Loss da ordem dependendo do seu tipo if(type==ORDER_TYPE_BUY_STOP) { request.type = ORDER_TYPE_BUY_STOP; request.tp = NormalizeDouble((high[rates_total1-2] + tpMax)/5,0) * 5; //request.sl = low[rates_total1-2]; //if (OpenSellOrder() >= 1) // request.sl = 10 + NormalizeDouble(low[rates_total1-2]/5,0) * 5; //else request.sl = SL_buy; request.price = NormalizeDouble(price,digits); //--- envio do pedido if(!OrderSend(request,result)) PrintFormat("OrderSend error %d",GetLastError()); // se não foi possível enviar o pedido, exibir o código de erro //--- informações sobre a operação PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order); Sleep(5000); candleOperado = candleCounter; //--- zerado dos valores do pedido e o seu resultado ZeroMemory(request); ZeroMemory(result); } } } } //Compra if(high[rates_total1-2] >= VWAP_Buffer_Daily && high[rates_total1-2] >= mediamovelrap[1] && high[rates_total1-2] >= mediamovellenta[1] && low[rates_total1-2] < VWAP_Buffer_Daily && low[rates_total1-2] < mediamovelrap[1] && PositionsTotal() == 0 && candleCounter != candleAnterior && candleOperado != candleCounter && Ask < high[rates_total1-2]) { if ((StringSubstr(horadata,0,5) >= horainicioOp) && (StringSubstr(horadata,0,5) <= horafimOp) ) { if (OpenBuyOrder() == 0) { double SL_buy = lowinverse[ArrayMinimum(lowinverse,1,slcomprado)]; double price; price = high[rates_total1-2]; // price for opening price = NormalizeDouble(price/5,0) * 5; MqlTradeRequest request={0}; MqlTradeResult result={0}; request.action = TRADE_ACTION_PENDING; // type of trade operation request.symbol = Symbol(); // symbol request.volume = volumeOp; // volume of 0.1 lot request.magic = EXPERT_MAGIC_BUY; // MagicNumber of the order double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT); // value of point int digits=SymbolInfoInteger(_Symbol,SYMBOL_DIGITS); // number of decimal places (precision) request.type = ORDER_TYPE_BUY_STOP; // order type request.type_filling = ORDER_FILLING_RETURN; request.type_time = ORDER_TIME_DAY; request.expiration = ORDER_TIME_GTC; request.sl = SL_buy; request.tp = NormalizeDouble((high[rates_total1-2] + tpMax)/5,0) * 5; // order triggering price //--- checking the type of operation request.price = NormalizeDouble(price,digits); // normalized opening price //--- send the request if(!OrderSend(request,result)) PrintFormat("OrderSend error %d",GetLastError()); // if unable to send the request, output the error code //--- information about the operation PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order); Sleep(5000); ZeroMemory(request); ZeroMemory(result); candleOperado = candleCounter; } } } //Stop para comprado if (low[rates_total1-2] > low[rates_total1-3] && PositionsTotal() > 0 && candleCounter != candleAnterior && candleOperado != candleCounter) { for(int i=0; i<PositionsTotal(); i++) { ulong position_ticket=PositionGetTicket(i);// ticket of the position string position_symbol=PositionGetString(POSITION_SYMBOL); // symbol int digits=(int)SymbolInfoInteger(position_symbol,SYMBOL_DIGITS); // number of decimal places ulong magic=PositionGetInteger(POSITION_MAGIC); // MagicNumber of the position double volume=PositionGetDouble(POSITION_VOLUME); // volume of the position double sl=PositionGetDouble(POSITION_SL); // Stop Loss of the position double tp=PositionGetDouble(POSITION_TP); // Take Profit of the position ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); // type of the position double SL_buy = lowinverse[ArrayMinimum(lowinverse,1,slcomprado)]; SL_buy = NormalizeDouble(SL_buy/5,0) * 5; //--- if the MagicNumber matches, Stop Loss and Take Profit are not defined if(magic==EXPERT_MAGIC_BUY && type==POSITION_TYPE_BUY && sl != SL_buy) { MqlTradeRequest request; MqlTradeResult result; ZeroMemory(request); ZeroMemory(result); //--- setting the operation parameters request.action = TRADE_ACTION_SLTP; // type of trade operation request.position= position_ticket; // ticket of the position request.symbol = position_symbol; // symbol request.tp = NormalizeDouble(tp/5,0) * 5; request.sl = NormalizeDouble(SL_buy/5,0) * 5; request.magic=EXPERT_MAGIC_BUY; // MagicNumber of the position //--- output information about the modification PrintFormat("Modify #%I64d %s %s",position_ticket,position_symbol,EnumToString(type)); //--- send the request if(!OrderSend(request,result)) PrintFormat("OrderSend error %d",GetLastError()); // if unable to send the request, output the error code //--- information about the operation PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order); Sleep(5000); ZeroMemory(request); ZeroMemory(result); candleOperado = candleCounter; } } } }
//**************************************************************************************************************** //**************************************************************************************************************** if (ordemvenda == true) { //Exclui ordem de venda abaixo da MM e Vwap if (OrdersTotal() > 0 && candleAnterior != candleCounter && candleOperado != candleCounter && low[rates_total1-2] > VWAP_Buffer_Daily && low[rates_total1-2] > mediamovelrap[1] && Ask > low[rates_total1-2]) { double NsVendaLs = highinverse[ArrayMaximum(highinverse,1,slvendido)]; for(int i=0; i<OrdersTotal(); i++) { ulong order_ticket=OrderGetTicket(i); // bilhete da ordem ulong magic=OrderGetInteger(ORDER_MAGIC); if(magic==EXPERT_MAGIC_SELL) { ZeroMemory(request); ZeroMemory(result); //--- setting the operation parameters request.action=TRADE_ACTION_REMOVE; // type of trade operation request.order = order_ticket; // order ticket //--- send the request if(!OrderSend(request,result)) PrintFormat("OrderSend error %d",GetLastError()); // if unable to send the request, output the error code //--- information about the operation PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order); Sleep(5000); ZeroMemory(request); ZeroMemory(result); candleOperado = candleCounter; } } } //Altera a ordem de venda if (low[rates_total1-2] >= low[rates_total1-3] && candleAnterior != candleCounter && candleOperado != candleCounter && OpenSellOrder() > 0) { //-- declaração e inicialização do pedido e o seu resultado //--- iterar todas as ordens pendentes colocadas for(int i=0; i<OrdersTotal(); i++) {// //--- parâmetros da ordem ulong order_ticket=OrderGetTicket(i); // bilhete da ordem string order_symbol=Symbol(); // símbolo int digits=(int)SymbolInfoInteger(order_symbol,SYMBOL_DIGITS); // número de signos depois da coma ulong magic=OrderGetInteger(ORDER_MAGIC); // MagicNumber da ordem double volume=OrderGetDouble(ORDER_VOLUME_CURRENT); // volume atual da ordem double sl=OrderGetDouble(ORDER_SL); // Stop Loss atual da ordem double tp=OrderGetDouble(ORDER_TP); // Take Profit atual da ordem ENUM_ORDER_TYPE type=(ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE); // tipo de ordem double price; // preço de ativação da ordem double point=SymbolInfoDouble(order_symbol,SYMBOL_POINT); // tamanho do ponto //--- saída de informações sobre a ordem //PrintFormat("#%I64u %s %s %.2f %s sl: %s tp: %s [%I64d]", order_ticket, order_symbol, EnumToString(type),volume, //DoubleToString(PositionGetDouble(POSITION_PRICE_OPEN),digits), //DoubleToString(sl,digits), DoubleToString(tp,digits), magic); //--- se o MagicNumber coincidir, o Stop Loss e o Take Profit nao foram definidos //if(magic==EXPERT_MAGIC_SELL && sl != high[rates_total1-2]) if(magic==EXPERT_MAGIC_SELL) { MqlTradeRequest request={0}; MqlTradeResult result={0}; double SL_venda = highinverse[ArrayMaximum(highinverse,1,slvendido)]; price = low[rates_total1-2]; // price for opening price = NormalizeDouble(price/5,0) * 5; request.type_filling = ORDER_FILLING_RETURN; request.expiration = ORDER_TIME_GTC; request.action=TRADE_ACTION_MODIFY; // tipo de operação de negociação request.order = OrderGetTicket(i); // bilhete da ordem request.symbol =Symbol(); // símbolo //--- definição do nível de preços Take Profit e Stop Loss da ordem dependendo do seu tipo if(type==ORDER_TYPE_SELL_STOP) { request.type = ORDER_TYPE_SELL_STOP; request.tp = NormalizeDouble((low[rates_total1-2] - tpMin)/5,0) * 5; if (OpenBuyOrder() >= 1) request.sl = NormalizeDouble(((high[rates_total1-2]/5) - 10),0) * 5; else request.sl = NormalizeDouble(SL_venda/5,0) * 5; request.price = NormalizeDouble(price,digits); } //--- envio do pedido if(!OrderSend(request,result)) PrintFormat("OrderSend error %d",GetLastError()); // se não foi possível enviar o pedido, exibir o código de erro //--- informações sobre a operação PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order); Sleep(5000); //--- zerado dos valores do pedido e o seu resultado ZeroMemory(request); ZeroMemory(result); candleOperado = candleCounter; } } } //Venda if(low[rates_total1-2] <= VWAP_Buffer_Daily && low[rates_total1-2] <= mediamovelrap[1] && low[rates_total1-2] <= mediamovellenta[1] && high[rates_total1-2] > VWAP_Buffer_Daily && high[rates_total1-2] > mediamovelrap[1] && PositionsTotal() == 0 && candleCounter != candleAnterior && candleOperado != candleCounter && Ask > low[rates_total1-2]) { if ((StringSubstr(horadata,0,5) >= horainicioOp) && (StringSubstr(horadata,0,5) <= horafimOp) ) { if (OpenSellOrder() == 0) { double SL_venda = highinverse[ArrayMaximum(highinverse,1,slvendido)]; double price; // order triggering price price = low[rates_total1-2]; // price for opening price = NormalizeDouble(price/5,0) * 5; MqlTradeRequest request={0}; MqlTradeResult result={0}; request.action = TRADE_ACTION_PENDING; // type of trade operation request.symbol = Symbol(); // symbol request.volume = volumeOp; // volume of 0.1 lot request.magic = EXPERT_MAGIC_SELL; // MagicNumber of the order double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT); // value of point int digits=SymbolInfoInteger(_Symbol,SYMBOL_DIGITS); // number of decimal places (precision) request.type = ORDER_TYPE_SELL_STOP; // order type request.type_filling = ORDER_FILLING_RETURN; request.type_time = ORDER_TIME_DAY; request.expiration = ORDER_TIME_GTC; if (OpenBuyOrder() >= 1) request.sl = (NormalizeDouble((high[rates_total1-2] - 10)/5,0)) * 5; else request.sl = SL_venda; request.tp = NormalizeDouble((low[rates_total1-2] - tpMin)/5,0) * 5; request.price = NormalizeDouble(price,digits); // normalized opening price //--- send the request if(!OrderSend(request,result)) PrintFormat("OrderSend error %d",GetLastError()); // if unable to send the request, output the error code //--- information about the operation PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order); Sleep(5000); ZeroMemory(request); ZeroMemory(result); candleOperado = candleCounter; } } } //Stop para vendido if (high[rates_total1-2] < high[rates_total1-3] && PositionsTotal() > 0 && candleCounter != candleAnterior && candleOperado != candleCounter) { for(int i=0; i<PositionsTotal(); i++) { ulong position_ticket=PositionGetTicket(i);// ticket of the position string position_symbol=PositionGetString(POSITION_SYMBOL); // symbol int digits=(int)SymbolInfoInteger(position_symbol,SYMBOL_DIGITS); // number of decimal places ulong magic=PositionGetInteger(POSITION_MAGIC); // MagicNumber of the position double volume=PositionGetDouble(POSITION_VOLUME); // volume of the position double sl=PositionGetDouble(POSITION_SL); // Stop Loss of the position double tp=PositionGetDouble(POSITION_TP); // Take Profit of the position ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); // type of the position double SL_venda = highinverse[ArrayMaximum(highinverse,1,slvendido)]; SL_venda = NormalizeDouble(SL_venda/5,0) * 5; //--- if the MagicNumber matches, Stop Loss and Take Profit are not defined if(magic==EXPERT_MAGIC_SELL && type==POSITION_TYPE_SELL && sl != SL_venda) { MqlTradeRequest request; MqlTradeResult result; //--- setting the operation parameters request.action = TRADE_ACTION_SLTP; // type of trade operation request.position= position_ticket; // ticket of the position request.symbol = position_symbol; // symbol request.tp = NormalizeDouble(tp/5,0) * 5; request.sl = SL_venda; request.magic = EXPERT_MAGIC_SELL; // MagicNumber of the position //--- output information about the modification PrintFormat("Modify #%I64d %s %s",position_ticket,position_symbol,EnumToString(type)); //--- send the request if(!OrderSend(request,result)) PrintFormat("OrderSend error %d",GetLastError()); // if unable to send the request, output the error code //--- information about the operation PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order); Sleep(5000); ZeroMemory(request); ZeroMemory(result); candleOperado = candleCounter; } } } } //*********************************************************************************************************************** //*********************************************************************************************************************** if ((OrdersTotal() >= 0 || PositionsTotal() >=0) && (StringSubstr(horadata,0,5) >= "16:40")) { for(int i=OrdersTotal()-1; i>=0; i--) { ulong order_ticket=OrderGetTicket(i); // order ticket ZeroMemory(request); ZeroMemory(result); //--- setting the operation parameters request.action=TRADE_ACTION_REMOVE; // type of trade operation request.order = order_ticket; // order ticket //--- send the request if(!OrderSend(request,result)) PrintFormat("OrderSend error %d",GetLastError()); // if unable to send the request, output the error code //--- information about the operation PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order); Sleep(5000); } } if ((PositionsTotal()>0) && (StringSubstr(horadata,0,5) >= "16:53")) { for(int i=0; i<OrdersTotal(); i++) { ulong magic=PositionGetInteger(POSITION_MAGIC); // MagicNumber of the position if(magic==EXPERT_MAGIC_BUY) { //printf (pos_profit); if (PositionGetDouble(POSITION_PROFIT) < 0) { if (trade.PositionClose(PositionGetSymbol(i))); } } if(magic==EXPERT_MAGIC_SELL) { //printf (pos_profit); if (PositionGetDouble(POSITION_PROFIT) < 0) { if (trade.PositionClose(PositionGetSymbol(i))); } } if(!OrderSend(request,result)) PrintFormat("OrderSend error %d",GetLastError()); // if unable to send the request, output the error code //--- information about the operation PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order); Sleep(5000); } } if ((PositionsTotal()>0) && (StringSubstr(horadata,0,5) >= "17:10")) { ZeroMemory(request); ZeroMemory(result); CloseAll(); Sleep(5000); } if (candleCounter != candleAnterior) { candleAnterior = candleCounter; } } //+------------------------------------------------------------------+
Tive que quebrar em três responstas, pelo limite de caracteres do forum.
Para rodar hoje na conta real, reiniciei o metatrader e recompilei o código, vamos ver como se comporta.
Como disse podem ter coisas a otimizar, mas no geral o código funciona perfeitamente na conta Demo.
Agradeço a ajuda.
Olá @maronezzi, não olhei o seu código completo, mas uma coisa me chamou à atenção, você está com a função OrderSend() dentro de um laço for, isto é muito perigoso e deve ser usado com muita atenção.
Sugiro você criar funções específicas para abrir, fechar e alterar ordens e posições, com nome bem descritivos, isso ajuda bastante a identificar bugs. Como você já está usando a classe "Trade" aproveite os recursos que ela oferece.
Outra dica, em último caso, é usar o debug na conta real. Isso ajuda a identificar situações que não acontecem em conta demo.
Olá @maronezzi, não olhei o seu código completo, mas uma coisa me chamou à atenção, você está com a função OrderSend() dentro de um laço for, isto é muito perigoso e deve ser usado com muita atenção.
Sugiro você criar funções específicas para abrir, fechar e alterar ordens e posições, com nome bem descritivos, isso ajuda bastante a identificar bugs. Como você já está usando a classe "Trade" aproveite os recursos que ela oferece.
Outra dica, em último caso, é usar o debug na conta real. Isso ajuda a identificar situações que não acontecem em conta demo.
@Gustavo Hennemann, hoje pretendo colocar em debug na conta real. Assim que a lógica ocorrer.
As minhas OrderSend() dentro de um for, estão nas alterações de stops, ou modificar uma ordem que já estava em aberto. A ordem seca de Buy não tem for.
O próximo passo para o script é colocar mais funções, indentar melhor o código e comenta-lo melhor também.
Obrigado pelos comentários.
Boa tarde Maronezzi,
sugiro diferenciar as mensagens do PrintFormat("retcode=%u ...) para melhor depuração do pgm.
Ex PrintFormat(" ORDEM PENDING BUY STOP retconde=%u ...).
- 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
Caros,
Criei um script de negociação automatizado, quando executo ele em conta demo funciona normal, mas quando executo na conta real para cada comando de BUY ou SELL é executado duas vezes.
Segue o código de Buy como exemplo:
Agradeço a ajuda.