Utilisez le bouton SRC pour placer le code, sinon les modérateurs vont simplement le supprimer !
Lisez également les nombreux autres fils de discussion qui mentionnent que les fonctions "A" ne sont plus prises en charge et que vous devrez utiliser les versions larges "W" des fonctions telles que "CreateNamedPipeW" au lieu de "CreateNamedPipeA".
Merci de m'avoir répondu et toutes mes excuses pour ne pas avoir collé le SRC sous forme de fichier.
En ce qui concerne votre réponse, cela signifie-t-il que je dois simplement remplacer la référence "A" des tuyaux nommés par une référence "W" ? J'ai essayé de rechercher des fils de discussion à ce sujet, mais je n'ai rien trouvé - votre aide est très appréciée. Merci encore.
Il ne s'agit pas de coller la source sous forme de fichier, mais d'utiliser l'outil SRC pour placer du code ici sur le forum. Comment utiliser le bouton SRC. (fourni par "RaptorUK")
Voici quelques références à des dilemmes similaires avec la version Wide de Functions :
Merci. Le côté serveur est maintenant capable de capturer le nombre d'appels après avoir mis à jour les tuyaux nommés 'A' à 'W'. Cependant, à partir de l'autre instance du MT4, il semble avoir des difficultés à recevoir l'entrée d'informations. J'ai mis à jour les tuyaux nommés à 'W' sur le côté réception mais il ne parvient toujours pas à tirer les données pour une raison quelconque. Avez-vous des idées ? Voir ci-dessous pour le code du côté récepteur :
extern double MaxDD = 30; extern double MM = 30; extern string PipeName = "Terminal"; extern string ServerPairName = ""; extern double BidCorrection = 0; extern double AskCorrection = 0; extern int APips = 2; extern int TPips = 5; extern int StopPips = 15; extern int VirtualStops = false; extern int ConfirmMS = 20; extern int SleepMS = 20; extern int Slippage = 1; extern int Magic = 2013; #define PIPE_BASE_NAME "\\\\.\\pipe\\mt4-" // MUST tally with client code #define ERROR_MORE_DATA 234 #import "kernel32.dll" int CallNamedPipeW(string PipeName, string outBuffer, int outBufferSz, int& inBuffer[], int inBufferSz, int& bytesRead[], int timeOut); #import datetime StartTime=0; double MinLots=0.1; double MaxLots=0.1; double LotStep=0.1; double MyPoint=0.0001; string MasterPair=""; double MaxBalance=0; double TotalPips=0; int TotalTrades=0; double EntrySlippage=0; int EntryMS=0; int OpenErrors=0; int LastTicket=0; double MasterBid=0; double MasterAsk=0; string LastQ=""; int init() { Comment("Initialization ..."); if(StringLen(ServerPairName)>=1) MasterPair=ServerPairName; else MasterPair=Symbol(); StartTime=0; return(0); } int deinit() { Comment(""); return(0); } int start() { double CurrentPips=0; string sInfo=""; if(IsStopped() || !IsConnected()) return(0); if(Digits<=3) MyPoint=0.01; MinLots=MarketInfo(Symbol(),MODE_MINLOT); MaxLots=MarketInfo(Symbol(),MODE_MAXLOT); LotStep=MarketInfo(Symbol(),MODE_LOTSTEP); if(StartTime<=0) { MaxBalance=AccountBalance(); StartTime=TimeLocal(); TotalPips=0; EntrySlippage=0; TotalTrades=0; EntryMS=0; LastTicket=0; OpenErrors=0; } while(!IsStopped()) { RefreshRates(); double dBid=Bid; double dAsk=Ask; int OldTicket=LastTicket; LastTicket=0; for(int j=OrdersTotal()-1; j>=0; j--) if(OrderSelect(j, SELECT_BY_POS, MODE_TRADES)) if((OrderSymbol() == Symbol()) && (OrderMagicNumber() == Magic)) { if(OrderType()==OP_BUY) CurrentPips=dBid-OrderOpenPrice(); else CurrentPips=OrderOpenPrice()-dAsk; CurrentPips=CurrentPips/MyPoint; LastTicket=OrderTicket(); } if(LastTicket==0 && OldTicket>0) if(OrderSelect(OldTicket, SELECT_BY_TICKET, MODE_HISTORY)) { if(OrderType()==OP_BUY) TotalPips=TotalPips+(OrderClosePrice()-OrderOpenPrice())/MyPoint; else TotalPips=TotalPips+(OrderOpenPrice()-OrderClosePrice())/MyPoint; } MaxBalance=MathMax(MaxBalance,AccountBalance()); if(AccountBalance()<=0) break; sInfo=""; CheckMaster(); if(MaxDD<=100*(MaxBalance-AccountBalance())/MaxBalance) sInfo=sInfo+"\nMaximum Drawdawn Reached !!!"; else if(MasterBid>=Point && MasterAsk>=Point) sInfo=sInfo+"\nBuy/Sell Levels: "+DoubleToStr((MasterBid-dAsk)/MyPoint-APips,1)+" / "+DoubleToStr((dBid-MasterAsk)/MyPoint-APips,1)+" pips"; else if(StringLen(LastQ)>0) sInfo=sInfo+"\nServer: "+LastQ; else sInfo=sInfo+"\nServer not working !!!"; if(LastTicket>0) sInfo=sInfo+", Position: "+DoubleToStr(CurrentPips,1)+" pips"; else if(MasterBid>=Point && MasterAsk>=Point && MaxDD>100*(MaxBalance-AccountBalance())/MaxBalance) { bool Oper=-1; if((dAsk)>=1.0000) Oper=OP_BUY; else if((dBid)>=1.0000) Oper=OP_SELL; if(Oper!=-1 && ConfirmMS>0) { Sleep(ConfirmMS); RefreshRates(); dBid=Bid; dAsk=Ask; CheckMaster(); if(Oper==OP_BUY) Oper=-1; if(Oper==OP_SELL) Oper=-1; } if(Oper!=-1 && IsTradeContextBusy()==false) { double Lots=MathMax(MinLots,MathMin(MaxLots,MathCeil((MM/100)*AccountFreeMargin()/LotStep/(100000/100))*LotStep)); int ExecutionTime=GetTickCount(); if(Oper==OP_BUY) LastTicket=OrderSend(Symbol(), OP_BUY, Lots, NormalizeDouble(dAsk,Digits), Slippage*MyPoint/Point, 0, 0, "", Magic,0,Blue); else LastTicket=OrderSend(Symbol(), OP_SELL, Lots, NormalizeDouble(dBid,Digits), Slippage*MyPoint/Point, 0, 0, "", Magic,0,Red); ExecutionTime=GetTickCount()-ExecutionTime; if(LastTicket<0) { OpenErrors=OpenErrors+1; } else { TotalTrades=TotalTrades+1; EntryMS=EntryMS+ExecutionTime; if(OrderSelect(LastTicket,SELECT_BY_TICKET)) if(OrderType()==OP_BUY) EntrySlippage=EntrySlippage+(dAsk-OrderOpenPrice())/MyPoint; else EntrySlippage=EntrySlippage+(OrderOpenPrice()-dBid)/MyPoint; } } } Comment("\nMagic# "+DoubleToStr(Magic,0)+", MM "+DoubleToStr(MM,2)+ ", Max DD: " + DoubleToStr(MaxDD,1)+"%, Current Drawdawn: "+DoubleToStr(100*(MaxBalance-AccountBalance())/MaxBalance,1)+" %"+ "\nMin Lot "+DoubleToStr(MinLots,2)+", Max Lot "+DoubleToStr(MaxLots,2)+", Lot Step "+DoubleToStr(LotStep,2)+", Stop Level "+DoubleToStr(MarketInfo(Symbol(),MODE_STOPLEVEL)*Point/MyPoint,1)+" pips"+ "\n"+sInfo+ "\nStart Time: "+TimeToStr(StartTime,TIME_DATE|TIME_SECONDS)+ "\nLocal Time: "+TimeToStr(TimeLocal(),TIME_DATE|TIME_SECONDS)+ "\nTotal Pips: "+DoubleToStr(TotalPips,1)+ "\nTotal Trades: "+DoubleToStr(TotalTrades,0)+ "\nEntry Errors: "+DoubleToStr(OpenErrors,0)+ "\nOpen Slippage: "+DoubleToStr(EntrySlippage,1)+" pips"+ "\nAverage Speed: "+DoubleToStr(EntryMS/MathMax(TotalTrades,1),0)+" ms"+ "\nAverage Slippage: "+DoubleToStr(EntrySlippage/MathMax(TotalTrades,1),1)+" pips" ); Sleep(MathMax(SleepMS,10)); if(IsTesting()) break; } return(0); } void CheckMaster() { MasterBid=0; MasterAsk=0; LastQ=""; if(IsTesting()) { MasterBid=NormalizeDouble(MarketInfo(MasterPair,MODE_BID)/2+MarketInfo(MasterPair,MODE_ASK)/2-MyPoint+2*MyPoint*(MathRand()-32767/2)/(32767/6),Digits); MasterAsk=MasterBid+2*MyPoint; } else { string MyPipeName = PIPE_BASE_NAME+PipeName; int inBuffer[2048]; int bytesRead[1]; string extMessage = MasterPair; bool fSuccess = CallNamedPipeW(MyPipeName,extMessage,StringLen(extMessage)+1,inBuffer,4*ArraySize(inBuffer),bytesRead,0) != 0; int lastError = GetLastError(); if(fSuccess/* || lastError == ERROR_MORE_DATA*/) { string inString = ""; for(int i=0; i<bytesRead[0]; i++) inString = inString + CharToStr( (inBuffer[i/4] >> ((i & 3)*8)) & 0xff); int ai=StringFind(inString, "|", 0); if(ai>0) { MasterBid=StrToDouble(StringSubstr(inString, 0, ai)); MasterAsk=StrToDouble(StringSubstr(inString, ai+1)); } LastQ=inString; } } if(MasterBid>0.0001) MasterBid=MasterBid+BidCorrection; if(MasterAsk>0.0001) MasterAsk=MasterAsk+AskCorrection; }
Changer "A" en "W" peut sembler trop facile. Il peut y avoir d'autres facteurs concernant les changements dans la nouvelle architecture et les fonctions Unicode qui doivent être pris en compte également.
Cependant, je ne sais pas s'il s'agit d'un bogue ou non, car je n'ai jamais utilisé Named Pipes avec MT4, mais vos "inBuffer" et "outBuffer" (dans "CallNamedPipeW") sont de types différents (l'un est "string" et l'autre "int"). Cela ne semble pas correct.
En fait, il se peut que ce soit tout à fait correct étant donné les astuces étranges de MetaTrader pour accomplir l'interaction DLL.
Je laisserai cette partie à quelqu'un qui est plus versé dans l'interface MT4-DLL.
J'ai également des problèmes avec les tuyaux nommés dans la dernière version de MT4.
J'ai remplacé WaitNamedPipeA par WaitNamedPipeW et cela fonctionne maintenant.
f (!WaitNamedPipeW( FullPipeName, 1)) { Comment(TimeToStr(TimeLocal(), TIME_DATE|TIME_MINUTES|TIME_SECONDS) + " " + PipeName + " not available"); Sleep(1000); continue; }
mais lorsque j'utilise CreateFileA ou CreateFileW, les deux appels se bloquent définitivement.
PipeHandle = CreateFileA(FullPipeName, GenericRead, 0, NULL, OPEN_EXISTING, 0, NULL) ;
Des idées / solutions ?
J'ai également des problèmes avec les tubes nommés dans la dernière version de MT4.
J'ai remplacé WaitNamedPipeA par WaitNamedPipeW et cela fonctionne maintenant.
Voici le fichier Server posté à l'origine (je n'oublierai pas de le poster dans SRC la prochaine fois)
extern string PipeName = "MetaTerminal1"; extern int SuspendSeconds = 10; extern int SleepMS = 10; #define PIPE_BASE_NAME "\\\\.\\pipe\\mt4-" #define GENERIC_READ 0x80000000 #define GENERIC_WRITE 0x40000000 #define PIPE_ACCESS_DUPLEX 3 #define PIPE_UNLIMITED_INSTANCES 255 #define PIPE_NOWAIT 1 #define PIPE_TYPE_MESSAGE 4 #define PIPE_READMODE_MESSAGE 2 #define PIPE_WAIT 0 #import "kernel32.dll" int CreateNamedPipeA(string pipeName,int openMode,int pipeMode,int maxInstances,int outBufferSize,int inBufferSize,int defaultTimeOut,int security); int PeekNamedPipe(int PipeHandle, int PassAsZero, int PassAsZero2, int PassAsZero3, int & BytesAvailable[], int PassAsZero4); int CreateFileA(string Filename, int AccessMode, int ShareMode, int PassAsZero, int CreationMode, int FlagsAndAttributes, int AlsoPassAsZero); int CloseHandle(int fileHandle); // int ReadFile(int FileHandle, int BufferPtr, int BufferLength, int & BytesRead[], int PassAsZero); int ReadFile(int FileHandle, int& inBuffer[],int BufferLength, int& BytesRead[], int lpOverlapped); int WriteFile(int FileHandle, string Buffer, int BufferLength, int & BytesWritten[], int PassAsZero); // int WriteFile(int FileHandle,int& inBuffer[], int NumberOfBytesToWrite, int& bytesWritten[], int lpOverlapped); int MulDiv(string X, int N1, int N2); #import // Number of pipe instances to create by default. This value can overridden by the optional parameter to // CreatePipeServer(). The number of instances is in effect the maximum number of messages which // can be sent to the server between each call which the server makes to CheckForPipeMessages(). // If more messages than this are sent, the extra messages will fail and the sender(s) will need to retry. #define DEFAULT_MAX_PIPES 200 // Number of pipe instances to allocate. Defaults to DEFAULT_MAX_PIPES unless it is overridden int glbPipeCount = DEFAULT_MAX_PIPES; // Array of pipe handles allocated by CreatePipeServer() int glbPipe[DEFAULT_MAX_PIPES]; // Persistent storage of the pipe name passed as a parameter to CreatePipeServer() string glbPipeName; // Starts the pipe server by creating n instances of the pipe void CreatePipeServer(string PipeName, int UsePipeInstances = DEFAULT_MAX_PIPES) { // Store the number of pipe instances to use and resize the array accordinging glbPipeCount = UsePipeInstances; ArrayResize(glbPipe, glbPipeCount); // Store the name to use for the pipe instances glbPipeName = PipeName; // Create the pipe instances for (int i = 0; i < glbPipeCount; i++) glbPipe[i] = CreatePipeInstance(); return; } // Closes all the resources used by the pipe server: i.e. closes all the pipe instances void DestroyPipeServer() { for (int i = 0; i < glbPipeCount; i++) CloseHandle(glbPipe[i]); return; } // Service function which creates a pipe instance int CreatePipeInstance() { string strPipeName = StringConcatenate(PIPE_BASE_NAME, glbPipeName); return (CreateNamedPipeA(strPipeName, GENERIC_READ | PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_NOWAIT, PIPE_UNLIMITED_INSTANCES, 1000, 1000, 0, NULL)); } datetime StartTime=0; int brCall=0; int aPairCount=0; string aPair[1000]; int aDigit[1000]; datetime aLastSinhTime[1000]; double aBid[1000]; double aAsk[1000]; int init() { StartTime=TimeLocal(); brCall=0; aPairCount=0; // Create the server CreatePipeServer(PipeName); return(0); } int deinit() { // Destroy the pipe server DestroyPipeServer(); Comment(""); return(0); } int start() { while(!IsStopped() && IsConnected()) { for(int i = 0; i < glbPipeCount; i++) CheckPipe(i); Comment("\nStart Time: "+TimeToStr(StartTime,TIME_DATE|TIME_SECONDS)+ "\nLocal Time: "+TimeToStr(TimeLocal(),TIME_DATE|TIME_SECONDS)+ "\nCall Count: "+DoubleToStr(brCall,0) ); Sleep(MathMax(SleepMS,10)); } return(0); } bool CheckPipe(int PipeIndex) { bool Result=false; string sMsg = ""; // See if there's data available on the pipe int BytesAvailable[1] = {0}; int res = PeekNamedPipe(glbPipe[PipeIndex], 0, 0, 0, BytesAvailable, 0); if (res != 0) { // PeekNamedPipe() succeeded // Is there data? if (BytesAvailable[0] != 0) { Result=true; // Keep reading until either we have all the data, or an error occurs int TotalBytesRead = 0; while (TotalBytesRead < BytesAvailable[0]) { string ReadBuffer=""; int iBuffer[256]; int BytesRead[1] = {0}; ReadFile(glbPipe[PipeIndex],iBuffer,4*ArraySize(iBuffer),BytesRead,NULL); for(int i=0; i<BytesRead[0]; i++) ReadBuffer = ReadBuffer + CharToStr( (iBuffer[i/4] >> ((i & 3)*8)) & 0xff); // Did we get any data from the read? if(BytesRead[0] > 0) { // Yes, got some data. Add it to the total message which is passed back sMsg = StringConcatenate(sMsg, StringSubstr(ReadBuffer, 0, BytesRead[0])); TotalBytesRead += BytesRead[0]; } else { // No, the read failed. Stop reading, and pass back an empty string sMsg = ""; TotalBytesRead = 999999; } } if(StringLen(sMsg)>0) { string outString="n/a"; RefreshRates(); brCall=brCall+1; double pBid=MarketInfo(sMsg,MODE_BID); double pAsk=MarketInfo(sMsg,MODE_ASK); if(pBid>0.0001 && pAsk>0.0001) { int ai=0; bool fl=true; for(i=1;i<=aPairCount;i++) if(aPair[i]==sMsg) { ai=i; break; } if(ai==0) { aPairCount=aPairCount+1; ai=aPairCount; aPair[ai]=sMsg; aDigit[ai]=MarketInfo(sMsg,MODE_DIGITS); aLastSinhTime[ai]=TimeLocal(); aBid[ai]=pBid; aAsk[ai]=pAsk; } else if(MathAbs(aBid[ai]-pBid)>=0.00001 || MathAbs(aAsk[ai]-pAsk)>=0.00001) { aLastSinhTime[ai]=TimeLocal(); aBid[ai]=pBid; aAsk[ai]=pAsk; } else if(TimeLocal()-aLastSinhTime[ai]>SuspendSeconds) fl=false; if(fl) outString=DoubleToStr(aBid[ai],aDigit[ai])+"|"+DoubleToStr(aAsk[ai],aDigit[ai]); else outString="Suspended"; } int bytesWritten[1]; bool fSuccess=WriteFile(glbPipe[PipeIndex],outString,StringLen(outString)+1,bytesWritten,NULL) != 0; if(!fSuccess || bytesWritten[0] != StringLen(outString)+1) { Sleep(10); } } // Destroy and recreate the pipe instance CloseHandle(glbPipe[PipeIndex]); glbPipe[PipeIndex] = CreatePipeInstance(); } else { // No data available on pipe } } else { // PeekNamedPipe() failed } return(Result); }
- Applications de trading gratuites
- Plus de 8 000 signaux à copier
- Actualités économiques pour explorer les marchés financiers
Vous acceptez la politique du site Web et les conditions d'utilisation
Bonjour,
Après cette récente mise à jour, je suis maintenant incapable de capturer le compte d'appel d'une instance de mon terminal MT4 pour le relayer sur un autre MT4. Pouvez-vous me dire ce qui a changé dans la mise à jour qui cause ce problème ? Vous trouverez ci-dessous le code qui continue à fonctionner correctement avec le build 509 mais pas après cette récente mise à jour.