sksyen:
谢谢你的回复,我为没有将SRC作为文件粘贴而道歉。
关于你的回答,这是否意味着我只需要将命名的管道 "A "的引用改为 "W"?我试着查找了一些关于这个问题的帖子,但没有找到--非常感谢您的帮助。再次感谢。
这不是把源码作为文件粘贴,而是使用SRC工具把代码放在论坛这里。 如何使用SRC按钮。( 由 "RaptorUK "提供)
这里有几个关于广义版本的函数的类似困境的参考资料。
谢谢你。 服务器端现在能够在更新命名的管道"A "到 "W "后捕捉到呼叫计数。 然而,从MT4的另一个实例来看,它在接收信息的输入方面似乎有困难。 我已经在接收端将名称管道更新为 "W",但由于某种原因,它仍然无法提取数据。 有什么想法吗? 请看下面的接收端代码。
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; }
"sksyen",你能不能修改你的原帖,把代码放在SRC部分。如果有一个版主去看这个,他们会删除帖子的那一部分,并要求你无论如何都要好好做。所以,在你不得不再次去寻找代码粘贴之前,现在就做吧。
在最新发布的MT4中,我也遇到了命名管道 的问题
我把WaitNamedPipeA改为WaitNamedPipeW,现在可以工作了
f (!WaitNamedPipeW( FullPipeName, 1)) { Comment(TimeToStr(TimeLocal(), TIME_DATE|TIME_MINUTES|TIME_SECONDS) + " " + PipeName + " not available"); Sleep(1000); continue; }
但当我使用CreateFileA或CreateFileW时,两个调用都会永久挂起。
PipeHandle = CreateFileA(FullPipeName, GenericRead, 0, NULL, OPEN_EXISTING, 0, NULL)。
有什么想法/解决方案吗?
这是最初发布的服务器文件(我下次会记得在SRC中发布)。
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); }
你好。
在最近的更新之后,我现在无法从我的MT4终端的一个实例中捕获调用计数,并将其转发到另一个MT4上。 你能告诉我在更新中发生了什么变化,导致这个问题吗? 以下是代码,在Build 509中可以继续正常工作,但在最近的更新后就不行了。