Grazie per aver risposto e le mie scuse per non aver incollato l'SRC come file.
Per quanto riguarda la tua risposta, questo significa che ho semplicemente bisogno di cambiare il riferimento ai tubi denominati "A" in un "W" invece? Ho provato a cercare alcuni thread riguardanti questo, ma non sono riuscito a trovare - il tuo aiuto è molto apprezzato. Grazie ancora.
Non si tratta di incollare il sorgente come file, ma di usare lo strumento SRC per mettere il codice qui sul forum. Come utilizzare il pulsante SRC. (fornito da "RaptorUK")
Qui ci sono un paio di riferimenti a dilemmi simili con la versione Wide di Functions:
Grazie. Il lato server ora è in grado di catturare il conteggio delle chiamate dopo aver aggiornato i tubi denominati "A" a "W". Tuttavia, dall'altra istanza dell'MT4, sembra avere problemi a ricevere l'input di informazioni. Ho aggiornato il nome dei tubi a "W" sul lato ricevente, ma ancora non riesce a tirare i dati per qualche motivo. Qualche idea? Vedi sotto per il codice sul lato di ricezione:
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; }
Cambiare "A" in "W" potrebbe sembrare troppo facile. Potrebbero esserci anche altri fattori relativi ai cambiamenti nella nuova architettura e alle funzioni Unicode che devono essere affrontati.
Comunque, non so se questo è un bug o no, perché non ho mai usato Named Pipes con MT4, ma il tuo "inBuffer" e "outBuffer" (in "CallNamedPipeW") sono di tipo diverso (uno è "string" e l'altro è "int"). Questo non sembra essere corretto.
In realtà, potrebbe essere totalmente corretto, dati gli strani trucchi di MetaTrader per realizzare l'interazione con le DLL.
Lascerò questa parte a qualcuno che è più esperto nell'interfacciamento tra MT4 e DLL.
Sto anche avendo problemi con i named pipe nell'ultima versione di MT4
Ho cambiato WaitNamedPipeA in WaitNamedPipeW e ora funziona
f (!WaitNamedPipeW( FullPipeName, 1)) { Comment(TimeToStr(TimeLocal(), TIME_DATE|TIME_MINUTES|TIME_SECONDS) + " " + PipeName + " not available"); Sleep(1000); continue; }
ma quando uso CreateFileA o CreateFileW, entrambe le chiamate si bloccano definitivamente
PipeHandle = CreateFileA(FullPipeName, GenericRead, 0, NULL, OPEN_EXISTING, 0, NULL);
Qualche idea / soluzione?
Sto anche avendo problemi con i named pipe nell'ultima versione di MT4
Ho cambiato WaitNamedPipeA in WaitNamedPipeW e ora funziona
Ecco il file Server postato originariamente (mi ricorderò di postarlo in SRC la prossima volta)
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); }
- App di trading gratuite
- Oltre 8.000 segnali per il copy trading
- Notizie economiche per esplorare i mercati finanziari
Accetti la politica del sito e le condizioni d’uso
Salve,
Dopo questo recente aggiornamento, ora non sono in grado di catturare il conteggio delle chiamate da un'istanza del mio terminale MT4 per trasmetterlo ad un altro MT4. Potete dirmi cosa è cambiato nell'aggiornamento che causa questo problema? Di seguito è riportato il codice che continua a funzionare bene con la build 509 ma non dopo questo recente aggiornamento.