☞ Named Pipe 기법을 이용하여 데이터를 전송받아 거래하는 EA, Chiggu에서 전송된 가격을 분석하여 주문을 내고(Open Spread), 청산(Close Spread)한다.


 설치는 Chiggu1(서버명 gguri), Chiranai2(서버명 chiggu)를 하나의 Broker에 설치하고, 다른 Broker에 Chiggu2(서버명 chiggu), Chiranai1(서버명 gguri)를 설치하여 각기 다른 차트에 Attach, 즉 하나의 통화를 거래하기 위해서는 동일 TF, Symbol당 2개의 차트가 필요( 하나의 pipe를 이용하여 =>, 다른 pipe를 이용하여 <= )하다. 


 실제 청산은 ClosingTime에서 설정된 가격이후에 조건충족시 청산가능. 다른 Broker에 하나씩 설치되어 다른 서버명(gguri, chiggu)을 가지고 독립적으로 거래 및 청산을 수행한다.

 

 Real Test 결과 데모버전의 경우 Peak Time에서나 뉴스Time과 같이 변동성이 심한 경우 데모가 리얼에 비해 느려지는 현상이 발생하여 신호의 왜곡현상이 발생하여 V0.4에서는 Close 조건을 슬리피지 이상 수익발생하고 청산스프레드 충족시 청산으로 조건을 변경할 필요가 있다.

 

//******************************************************************************
//|                                                     YS_NP_Sub_chiggu_V0.4         |
//|                                             Copyright @ Gguri FX LAB             |
//******************************************************************************


/*
Time Frame : Any Pairs
Pairs : EURUSD, GBPUSD, USDJPY, EURGBP, AUDUSD, USDCAD 등(브로커별로 확인요망)
Based Indicator : Named Pipe
Start Date : 2012-09-20
Logic : Data Sender(Named Pipe)

//******************************************************************************
//| Version History                                                            |
//******************************************************************************

 0.1 Version 
 - Named Pipe mqh file(Clent, Server)을 이용하여 가격정보 전달 및 화면 표시 기능
 - Named Pipe mqh file을 하나로 통합
 - USDJPY 과 같은 통화에 대한 대응
 - Named Pipe mqh file을 내재화
 - Buy, Sell 조건의 기초작업(스프레드 차이 변수화 작업)
 - Buy, Sell 주문 및 청산 로직 추가
 - Pipe 추가 및 가격정보 역전송
 - 수익계산 및 오더수 계산하여 화면표시
 - Ready 추가
 - Adjust함수 추가, magicnumber 수정
 - 화면표시 정보수정
 - Reverse와 분리
 - Ready 내생변수
 - Ready값에 따른 주문변경
 - 화면표시 정보수정

*/

//******************************************************************************
//| 상수설정                                                                   |
//******************************************************************************

#define EA_NAME "YS_NP_Sub_chiggu_V0.4"
#define Copyrights ""
#define Create_Date "2012-09-20"

//******************************************************************************
//| Import Library  & Include                                                  |
//******************************************************************************

#import "stdlib.ex4"
   string ErrorDescription(int a0);

// Named Pipe Include File Import

#define DEFAULT_MAX_PIPES  20

// Base name to use for pipe creation
#define PIPE_BASE_NAME     "\\\\.\\pipe\\mt4-"   

//*********************************************************************************************
// DLL imports and associated constants used by the pipe server
//*********************************************************************************************

#define GENERIC_READ                   0x80000000
#define GENERIC_WRITE                  0x40000000
#define OPEN_EXISTING                  3
#define INVALID_HANDLE_VALUE           -1
#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 WriteFile(int FileHandle, string Buffer, int BufferLength, int & BytesWritten[], int PassAsZero);
   int MulDiv(string X, int N1, int N2);

#import

//******************************************************************************
//| 내외생변수 설정                                                            |
//******************************************************************************

extern string  ServerName = "chiggu";             // 서버이름설정, 통화마다 다르게 설정됨.
extern int     RetryForSeconds = 0;
extern int MinBars = 100;                         // 최소 다운로드 Bar의 수
string  PriceInfo = "";

string NowSym, ServerN,StartDay;                  // EA 시작일 및 심볼 조정변수
// MarketInfo 정보를 받는 변수
string broker,servername,mytime,sympoint,spread;
double equity,reqmargin,stopout,minlot,maxlot,LotStep,asks,bids;
int leverage,mydigit,stoplevel,freeze;

// *********************************************************************************************
// Global variables used by the pipe server
// *********************************************************************************************

int glbPipeCount = DEFAULT_MAX_PIPES;
int glbPipe[DEFAULT_MAX_PIPES];
string glbPipeName;

// *********************************************************************************************
// Simple function for sending a message to a server
// *********************************************************************************************

bool SendPipeMessage(string ToPipe, string Message, int RetryForSeconds = 0) {
   // Try an initial send 
   if (SendPipeMessage2(ToPipe, Message)) {
      return (true);
   
   } else {
      // The initial send failed. Consider doing retries
      if (RetryForSeconds <= 0) {

         // Retries not allowed 
         return (false);
      
      } else {
         // Keep retrying for n seconds 
         int RetryUntilTime = TimeLocal() + RetryForSeconds;
         while (TimeLocal() < RetryUntilTime) {
            if (SendPipeMessage2(ToPipe, Message)) {
               return (true);
            } else {
               // Keep retrying - with a small pause between attempts
               Sleep(100);
            }
         }

         return (false);
      }
   }
}

bool SendPipeMessage2(string ToPipe, string Message) {
   bool bReturnvalue = false;
   
   string strPipeName = StringConcatenate(PIPE_BASE_NAME , ToPipe);
 
   // Try opening a connection to a free instance of the pipe  
   int PipeHandle = CreateFileA(strPipeName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
   if (PipeHandle == INVALID_HANDLE_VALUE) {

      bReturnvalue = false;

   } else {
      int BytesWritten[1] = {0};
      WriteFile(PipeHandle, Message, StringLen(Message), BytesWritten, 0);
   
      if (BytesWritten[0] > 0) {
         bReturnvalue = true;
      } else {
         bReturnvalue = false;
      }
   
      CloseHandle(PipeHandle);
   }
   
   return (bReturnvalue);
}

void DestroyPipeServer() {
   for (int i = 0; i < glbPipeCount; i++) {
      CloseHandle(glbPipe[i]);
   }
   return;
}


//******************************************************************************
//| 초기화                                                                     |
//******************************************************************************

int init() {  // 8

// 거래 가능여부 확인
   if(IsTradeAllowed()) {
    Print("거래 가능합니다!");
   }
   
// Period Protection
   if(Period() != PERIOD_M1) {
     Alert("1분봉 차트에 붙이셔야 합니다.");
     return(0);
   }  

// Symbol Protection
   if (StringSubstr(Symbol(), 0, 6) != "GBPUSD" && StringSubstr(Symbol(), 0, 6) != "EURUSD" && StringSubstr(Symbol(), 0, 6) != "USDJPY" && StringSubstr(Symbol(), 0, 6) != "EURGBP") {
      Alert("GBPUSD,EURUSD,USDJPY,EURGBP 말고는 취급안해!");
      return (0);
   }  

// EA 시작일 설정
     StartDay = TimeToStr(TimeCurrent(),TIME_DATE); 

// 접미사형태의 통화대처를 위해 심볼명의 6자리까지 심볼명으로 지정
     NowSym = StringSubstr(Symbol(), 0, 6);
     ServerN = StringConcatenate( ServerName , NowSym ); 

}  // 8

//******************************************************************************
//| 종료시 설정                                                                |
//******************************************************************************

int deinit()  {
   // Destroy the pipe server 
   DestroyPipeServer();
   return(0);
  }

//******************************************************************************
//| EA Start                                                                   |
//******************************************************************************

int start() {  // 0

//******************************************************************************
// Error 검출후 메세지 출력

// Server와 연결이 안된 경우
  if(!IsConnected()) {  
     Print("연결해주세요!");
     return(0);
   }

// EA 거래를 막아놓은 경우

  if(!IsTesting()) {
   if(!IsDllsAllowed() || !IsExpertEnabled()) {
     Print("DLL 사용할 수 있게 옵션에서 풀어주세요. 혹은 EA아이콘 확인요망!");
     return(0);
     }
  }  

//******************************************************************************
// 데이타 다운로드 미비에 의한 오류계산 방지 로직

   bool DataEnabled = TRUE;    
   if(iBars(Symbol(), 0) < MinBars) {
     DataEnabled = FALSE;
     Print ("아! Bar가 아직 모자라!ㅠㅠ..");
   }


//******************************************************************************
// MarketInfo 정보를 받는 변수 설정

    broker     = AccountCompany();
    servername = AccountServer();
    mytime     = TimeToStr(TimeCurrent(),TIME_SECONDS);
    equity     = AccountEquity();
    leverage   = AccountLeverage();       
    reqmargin  = MarketInfo(Symbol(), MODE_MARGINREQUIRED);

    double asks = MarketInfo(Symbol(),MODE_ASK);
    double bids = MarketInfo(Symbol(),MODE_BID);

    stoplevel  = MarketInfo(Symbol(), MODE_STOPLEVEL);
    freeze     = MarketInfo(Symbol(), MODE_FREEZELEVEL);    
    stopout    = AccountStopoutLevel();
    mydigit    = MarketInfo(Symbol(), MODE_DIGITS);
    sympoint   = DoubleToStr(MarketInfo(Symbol(),MODE_POINT),mydigit);
    minlot     = MarketInfo(Symbol(), MODE_MINLOT);
    maxlot     = MarketInfo(Symbol(), MODE_MAXLOT);
    LotStep    = MarketInfo(Symbol(), MODE_LOTSTEP);
    spread     = DoubleToStr(NormalizeDouble(asks-bids,mydigit),mydigit);     

//******************************************************************************
// 화면표시 및 데이타 전송관련 변수 설정

    string writes;  // 화면에 표시할 데이타의 문자열   
    string DataFeeds[4];  // 화면에 표시 및 전송할 데이타의 배열


//******************************************************************************
//| 화면표시 및 데이타 전송                                                    |
//******************************************************************************

/*
string TimeToStr(datetime value, int mode=TIME_SECONDS), TIME_SECONDS gets result as "hh:mm:ss".
현재시각을 "hh:mm:ss" 형태로 표시하여 저장, ASK, BID가격도 함께 배열에 저장
*/ 
   DataFeeds[0]=TimeToStr(TimeCurrent(),TIME_SECONDS);
   DataFeeds[1]=adjust(asks);
   DataFeeds[2]=adjust(bids);
   DataFeeds[3]=StringSubstr(DoubleToStr(MarketInfo(Symbol(), MODE_DIGITS),1),0,1);

// DataFeeds배열의 4개값을 화면에 표시
     writes = StringConcatenate("EA Name : ",EA_NAME," , Copyright : ",Copyrights," , EA제작일_",Create_Date," , 현재시간 : ",mytime," 평가잔액 = $",equity," Leverage_",leverage,":1, 1Lot당 필요증거금 : $",reqmargin)+"\n";     
     writes = writes + StringConcatenate("Broker : ",broker," Server : ",servername,", EA시작일_",StartDay," StopLevel_",stoplevel," Freeze Level_",freeze," Stop Out_",stopout,"%, Digit_",mydigit)+"\n";
     writes = writes + StringConcatenate("접속명 : ",ServerN,", Point_",sympoint," Min Lot_",minlot," Max Lot_",maxlot," Lot Step_",LotStep," Spread_",spread," Data_",DataEnabled)+"\n";
     writes = writes + "===========================================================================================================" + "\n";     
     writes = writes + StringConcatenate("TimeSeconds : ",DataFeeds[0], " Ask = ",DataFeeds[1]," Bid = ", DataFeeds[2], ", Digit = ",DataFeeds[3]);
     Comment(writes);
     
     PriceInfo = StringConcatenate(DataFeeds[3], DataFeeds[0],";", DataFeeds[1],";", DataFeeds[2]) ;
   
     if ( SendPipeMessage(ServerN, PriceInfo, RetryForSeconds) ) {  // 3                     
     return;                     
     }  // 3        
     else        
     {  // 4
     Print("앗, 접속불량!");
     return;
     } // 4 
          
}  // 0

//******************************************************************************
//| 데이타 조정함수                                                            |
//******************************************************************************

string adjust(double gets)
  {  // 0
   string ad;
   if (gets >= 0 && gets < 10) ad = DoubleToStr(NormalizeDouble(gets, 5),5);
   if (gets >=10 && gets < 100) ad = DoubleToStr(NormalizeDouble(gets, 4),4);
   if (gets >=100 && gets < 1000) ad = DoubleToStr(NormalizeDouble(gets, 3),3);
   if (gets >=1000 && gets < 10000) ad = DoubleToStr(NormalizeDouble(gets, 2),2);
   if (gets >=10000 && gets < 100000) ad = DoubleToStr(NormalizeDouble(gets, 1),1);
   return (ad);

  }   // 0

'IT관련' 카테고리의 다른 글

메타트레이더 EA - Winner H4  (0) 2019.09.21
메타트레이더 EA - RT IlmokCloud  (0) 2019.09.20
메타트레이더 EA - Named Pipe Main  (0) 2019.09.18
메타트레이더 EA - GV Import  (0) 2019.09.17
메타트레이더 EA - GV Export  (0) 2019.09.16

+ Recent posts