Verwenden Sie die SRC-Schaltfläche, um den Code zu platzieren, sonst werden die Moderatoren ihn einfach löschen!
Lesen Sie auch die vielen anderen Threads, die erwähnt haben, dass die "A" -Funktionen nicht mehr unterstützt werden und Sie die "W"-Weit-Versionen der Funktionen wie "CreateNamedPipeW" anstelle von "CreateNamedPipeA" verwenden müssen.
Vielen Dank für Ihre Antwort und meine Entschuldigung, dass ich den SRC nicht als Datei eingefügt habe.
Was Ihre Antwort betrifft, bedeutet das, dass ich die "A"-Referenz der benannten Rohre einfach in eine "W"-Referenz ändern muss? Ich habe versucht, einige Threads zu diesem Thema zu finden, konnte aber nichts finden - Ihre Hilfe wird sehr geschätzt. Nochmals vielen Dank.
Es geht nicht um das Einfügen des Quelltextes als Datei, sondern um die Verwendung des SRC-Tools, um den Code hier im Forum zu platzieren. Wie man die SRC-Schaltfläche verwendet. (bereitgestellt von "RaptorUK")
Hier sind ein paar Verweise auf ähnliche Probleme mit der Wide-Version von Functions:
Ich danke Ihnen. Die Serverseite ist nun in der Lage, die Anzahl der Anrufe zu erfassen, nachdem die benannten Leitungen "A" auf "W" aktualisiert wurden. Von der anderen Instanz des MT4 scheint es jedoch Probleme zu haben, die Eingabe von Informationen zu empfangen. Ich habe die Named Pipes auf der Empfängerseite auf "W" aktualisiert, aber aus irgendeinem Grund gelingt es immer noch nicht, die Daten abzurufen. Hat jemand eine Idee? Siehe unten für den Code auf der Empfangsseite:
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; }
Die Änderung von "A" in "W" könnte zu einfach erscheinen. Möglicherweise gibt es noch andere Faktoren im Zusammenhang mit den Änderungen in der neuen Architektur und den Unicode-Funktionen, die ebenfalls berücksichtigt werden müssen.
Ich weiß jedoch nicht, ob es sich um einen Fehler handelt oder nicht, da ich noch nie Named Pipes mit MT4 verwendet habe, aber Ihre "inBuffer" und "outBuffer" (in "CallNamedPipeW") sind von unterschiedlichem Typ (einer ist "string" und der andere "int"). Das scheint nicht korrekt zu sein.
Es könnte sogar völlig korrekt sein, wenn man die seltsamen Tricks von MetaTrader bei der DLL-Interaktion bedenkt.
Ich werde diesen Teil jemandem überlassen, der sich mit der Interaktion zwischen MT4 und DLL besser auskennt.
Ich habe auch Probleme mit Named Pipes in der neuesten Version von MT4
Ich habe WaitNamedPipeA in WaitNamedPipeW geändert und das funktioniert jetzt
f (!WaitNamedPipeW( FullPipeName, 1)) { Comment(TimeToStr(TimeLocal(), TIME_DATE|TIME_MINUTES|TIME_SECONDS) + " " + PipeName + " not available"); Sleep(1000); continue; }
aber wenn ich entweder CreateFileA oder CreateFileW verwende, bleiben beide Aufrufe permanent hängen
PipeHandle = CreateFileA(FullPipeName, GenericRead, 0, NULL, OPEN_EXISTING, 0, NULL);
Irgendwelche Ideen/Lösungen?
Ich habe auch Probleme mit Named Pipes in der neuesten Version von MT4
Ich habe WaitNamedPipeA in WaitNamedPipeW geändert und das funktioniert jetzt.
Hier ist die Server-Datei, die ursprünglich gepostet wurde (ich werde daran denken, sie das nächste Mal im SRC zu posten)
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); }
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.
Hallo,
Nach dem letzten Update kann ich die Anzahl der Anrufe von einem MT4-Terminal nicht mehr erfassen und an einen anderen MT4 weiterleiten. Können Sie mir sagen, was sich durch das Update geändert hat, das dieses Problem verursacht? Im Folgenden finden Sie den Code, der mit Build 509 weiterhin gut funktioniert, nach dem jüngsten Update jedoch nicht mehr.