다중 통화 지표를 개발하는 방법을 아는 사람이 있습니까? - 페이지 3

 
4x_Gypsy :

큰 단서는 "하지만 나는 이것을 하는 방법을 모른다."였다.

OP에서 어떤 종류의 응답도 없다는 것은 문제가 있다는 표시입니다. 내 "추측"은 OP가 이해 부족으로 좌절하고 스레드를 포기했다는 것입니다. 몇 년 전에도 같은 일을 하던 때가 있었습니다. 내가 얼마나 새로운지 깨닫는 데 시간을 할애하는 사람이 없었고 계속해서 사례를 게시하고 당시 내 이해를 완전히 뛰어넘는 토론을 했기 때문에 나는 이것보다 다른 사이트/포럼에서 더 많은 것을 배웠습니다.

당신의 관점을 형성하면 당신이 옳을 수 있습니다. 반면에 나는 단지 위험을 감수하고 문서를 빠르게 살펴보고 그 질문에 계속해서 대답하는 것이 바보 같다고 느끼면 단순히 대답되는 많은 질문을 보았습니다.

또한 여기에 Google 및 검색 옵션이 있습니다. 어떻게 해야 할지 모르겠다면 스스로 문제를 해결하기 위한 다음 단계입니다.

이 스레드의 주제인 경우 다중 통화 시스템을 코딩하는 방법을 모릅니다. Google에 답변하거나 여기에서 이미 존재하는 코드를 검색했을 것입니다.

 
gooly :

당신의 관점을 형성하면 당신이 옳을 수 있습니다. 반면에 나는 단지 위험을 감수하고 문서를 빠르게 살펴보고 그 질문에 계속해서 대답하는 것이 바보 같다고 느끼면 단순히 대답되는 많은 질문을 보았습니다.

또한 여기에 Google 및 검색 옵션이 있습니다. 어떻게 해야 할지 모르겠다면 스스로 문제를 해결하기 위한 다음 단계입니다.

이 스레드의 주제인 경우 다중 통화 시스템을 코딩하는 방법을 모릅니다. Google에 답변하거나 여기에서 이미 존재하는 코드를 검색했을 것입니다.

피드백을 주셔서 감사합니다. 긍정적이었습니다. ㅋㅋㅋ

이 상황에서 내가 만난 방식에 대해 걱정하는 사람에게 미안합니다. 나는 진정으로 내가 동의하지 않는 대부분의 것들을 무시하는 평화를 사랑하는 드라마 자유로운 종류의 사람입니다.

 

안녕하세요 여러분,

여기에서 오랫동안 활동하지 못해 죄송합니다. 출퇴근도 하고 프로젝트도 바빠서 한동안 프로젝트를 미루게 되었어요..

게시물 업데이트를 읽은 후 명확히 할 몇 가지 사항이 있습니다.

  1. 나는 누군가가 나를 위해 모든 것을 코딩하는 것을 원하지 않으며, 나에게 올바른 방향을 보여주기만 하면 되고 나머지는 내가 합니다. 음... 지금 WHRoeder 솔루션을 테스트하고 내 것을 만들고 나중에 결과를 여기에 게시할 것입니다. WHRoeder 제안: https://www.mql5.com/en/forum/158938
  2. 이 주제를 만들기 전에 비슷한 게시물을 검색했지만 찾지 못했습니다... 그런 다음 작성
  3. 답변에 시간이 오래 걸려서 죄송합니다만 정말 과로했는데 지금은 계속 인디케이터 작업을 하고 있습니다
  4. 내 가난한 영어에 대해 죄송합니다! 내 언어는 포르투갈어이고 영어를 게시할 때 Google 번역기를 사용해야 하는데 완벽하지 않습니다.


 
여기 내 테스트.

사용자가 자산을 알리도록 허용한 후 모든 쌍의 High/Low 값을 표시합니다.

selectec 쌍 중 하나라도 활성 창과 같으면 그의 비율이 잘 업데이트됩니다. 그러나 다른 쌍은 지표가 추가되었을 때만 비율을 표시하고 더 이상 업데이트하지 않습니다...

아래 이미지에서 볼 수 있듯이 GBPUSD 창에 지표가 추가되었고... GBPUSD 환율은 틱 단위로 미세하게 업데이트되었습니다. 그러나 EURUSD는 업데이트되지 않고 여전히 동일한 가치를 유지합니다.

요금 복사됨


아래에 표시기 코드:

 //+------------------------------------------------------------------+
//|                                                MultiCurrency.mq4 |
//|                         Copyright 2016, Wemerson Couto Guimarães |
//|                  https://www.mql5.com/pt/users/wemersonrv/seller |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Wemerson Couto Guimarães"
#property link        "https://www.mql5.com/pt/users/wemersonrv/seller"
#property version    "1.00"
#property strict
#property indicator_separate_window

input string UsePairs= "EURUSD,GBPUSD" ; // Pares separados por vírgula.

struct pair_struct{
   string symbol;
   MqlRates rates[];
};
pair_struct pairs[];
bool initial;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit (){
   int i= 0 , j= 0 , c;
   string _pairs[], msg= "" ;
   bool pairok= false ;
   initial = true ;
   ENUM_INIT_RETCODE result = INIT_SUCCEEDED ;
   
   StringSplit (UsePairs, StringGetCharacter ( "," , 0 ), _pairs);
   
   for ( i= 0 ; i< ArraySize (_pairs); i++){
      pairok= false ;
      
       for ( j= 0 ; j< SymbolsTotal ( true ); j++){
         if ( SymbolName (j, true ) == _pairs[i]){
            pairok= true ;
             break ;
         }
      }
       if ( pairok ){
         c= ArraySize (pairs);
         ArrayResize (pairs, c+ 1 );
         pairs[c].symbol = _pairs[i];
      } else {
         msg += _pairs[i] + ", " ;
      }
   }
   if ( msg != "" ){
       string invalids = ArraySize (pairs)== 1 ? "Invalid Pair: " : "Invalid Pairs: " ;
      msg = invalids +   StringSubstr (msg, 0 , StringLen (msg)- 2 ) + ". Please Check!" ;
       Alert (msg);
      result = INIT_PARAMETERS_INCORRECT ;
   } else {
       for (i= 0 ; i< ArraySize (pairs); i++){
         ArrayCopyRates( pairs[i].rates, pairs[i].symbol, PERIOD_CURRENT );
      }
   }   
   
   return (result);

}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit ( const int reason){
   
   Comment ( "" );
   
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate ( const int rates_total,
                 const int prev_calculated,
                 const datetime &time[],
                 const double &open[],
                 const double &high[],
                 const double &low[],
                 const double &close[],
                 const long &tick_volume[],
                 const long &volume[],
                 const int &spread[])
  {

   int i= 0 ;
   if ( initial ){
       for ( i= 0 ; i< ArraySize (pairs); i++){
         if (pairs[i].rates[ 0 ].time == 0 ) return (rates_total);
      }
      initial= false ;
   }
   
   string log = "" ;
   
   for (i= 0 ; i< ArraySize (pairs); i++){
       log += "\nPair: " + pairs[i].symbol + 
             " - High: " + DoubleToStr(pairs[i].rates[ 0 ].high, Digits ()) + 
             " - Low: " + DoubleToStr(pairs[i].rates[ 0 ].low, Digits ());
   }

   Comment ( "\n\n*** Pair Rates***\n" + log );
   return (rates_total);
   
}
//+------------------------------------------------------------------+

 
나는 RefreshRates() 를 사용하려고 하지만 여전히 같은 결과를 가지고 있습니다... 같은 창에 있는 쌍만 작동하고 다른 쌍은 업데이트되지 않습니다.
 
wemersonrv :
나는 RefreshRates() 를 사용하려고 하지만 여전히 같은 결과를 가지고 있습니다... 같은 창에 있는 쌍만 작동하고 다른 쌍은 업데이트되지 않습니다.

RefreshRates()MqlRates 데이터와 아무 관련이 없습니다. WHRoeder의 예제 코드는 Pre-600 빌드에서만 유효합니다. 최신 빌드의 경우 ArrayCopyRates() 의 반환 코드 테스트, 오류 코드, Rates Array의 크기 및 WHRoeder 가 지적한 추가 예방 조치와 같이 내 게시물에 언급된 다양한 사항 을 확인해야 합니다. 시간 속성의 유효성.

추신! 영어가 어려우시면 저에게 PM을 보내주세요. 나는 포르투갈 사람입니다(포르투갈)

 

안녕 얘들아.

테스트, 나는 모든 반복에서 먼저 쌍의 배열을 해제하는 루프를 추가하여 OnCalculate 함수 에 비율의 "복사"를 포함시킨 다음 비율을 다시 복사합니다. 작동하는 것으로 보이며 오류를 반환하지 않습니다.

이것이 내가 필요한 것을 수행하는 가장 좋은 방법인지 모르겠지만 분명히 작동하고 오류가 없습니다.


   int i= 0 ;
   if ( initial ){
       for ( i= 0 ; i< ArraySize (pairs); i++){
         if (pairs[i].rates[ 0 ].time == 0 ) return (rates_total);
      }
      initial= false ;
   }

   // My change to recopy rates every tick by adding a loop at starting of OnCalculate() to do this
   // AS FMIC says, ArrayCopyRates needs the array without content, 
   // then before recopy, free the array.
   for (i= 0 ; i< ArraySize (pairs); i++){
       ArrayFree (pairs[i].rates);
      ArrayCopyRates(pairs[i].rates, pairs[i].symbol, PERIOD_CURRENT );
   }
 
wemersonrv : 테스트, OnCalculate 함수에 비율의 "복사"를 포함했습니다... 모든 반복에서 쌍의 배열을 먼저 해제한 다음 비율을 다시 복사하는 루프를 추가하여... 작동하는 것으로 보이며 오류를 반환하지 않습니다.
  1. 설명서 에 명시된 대로 .
    다른 차트에서 데이터(기호 이름 및/또는 시간 프레임이 다른 경우)를 요청하는 경우 클라이언트 단말에서 해당 차트가 열리지 않고 서버에서 필요한 데이터를 요청해야 하는 상황이 발생할 수 있습니다. 이 경우 오류 ERR_HISTORY_WILL_UPDATED(4066 - 요청된 기록 데이터가 업데이트 중임)가 last_error 변수에 배치되고 다시 요청해야 합니다.
    그리고여기에서 확인
    ArrayCopyRates는 기록이 전혀 없으면 오류를 반환합니다(ERR_NO_HISTORY_DATA = 4073.). 반복 호출도 다운로드가 완료될 때까지 실패합니다. 기록이 있지만 최신 상태가 아닌 경우 ArrayCopyRates는 유효한 값을 반환하고 `_LastError`도 ERR_HISTORY_WILL_UPDATED(= 4066)로 설정합니다.
  2. 반환 코드를 테스트하고 필요한 경우 잠자기 상태에서 재시도하십시오. 함수 반환 값이란 무엇입니까? 어떻게 사용합니까? - MQL4 포럼MQL4 프로그램의 일반적인 오류 및 이를 방지하는 방법 - MQL4 기사
 

이 스레드를 팔로우하는 사람들에 대한 업데이트입니다!

나는 PM을 통해 OP가 영어에 어려움을 겪고 우리 둘 다 포르투갈어를 사용하기 때문에 코드를 수정하는 것을 도왔습니다. 테스트에서 " ArrayCopyRates() " 함수에서 발생하는 또 다른 "재미"를 발견했습니다. EA에서 " ArrayCopyRates() "와 함께 MqlRates 배열을 사용할 때 데이터 배열은 항상 사물의 현재 상태를 보고하는 가상 배열이므로 데이터는 항상 최신 상태입니다.

그러나 지표에서는 그렇지 않은 것 같습니다. 어레이는 가상 복사본이 아니라 " ArrayCopyRates() "가 호출된 순간에 설정된 정적 복사본입니다. 기호가 차트 기호와 다른 경우 데이터가 업데이트되지 않습니다. 차트와 동일한 기호인 경우 배열 데이터는 "라이브"이고 예상대로 업데이트되지만 다른 기호의 경우에는 정적 복사본입니다.

따라서 표시기에서 작동하려면 새 데이터가 필요한 경우 OnCalculate() 이벤트를 호출할 때마다 " ArrayCopyRates() " 함수를 호출해야 합니다.

 

안녕 모두.

  • FMIC , 지원해주셔서 감사합니다!
  • WHRoeder님 , 너무 감사합니다... 당신은 항상 우리 모두를 위해 거기에 있습니다!
  • 귀하의 고려 사항에 대해 모든 포럼 회원에게 감사하고 이 스레드에서 생성된 전체 토론에도 감사드립니다. 그건 진짜 흥미 로웠 어. !

이것은 (거의) 내가 나중에 하는 것과 같지만 차이점은 ArrayCopyRates 전에 ArrayFree를 실행한다는 것입니다... 그리고 당신이 나를 도운 유효성 검사를 하지 않습니다.

다음은 FMIC가 저에게 도움을 준 최종 코드입니다. 이제 표시기 코드에서 정상적으로 작동합니다..:

 input string UsePairs= "NZDCAD,EURUSD,GBPUSD,USDJPY" ; // pairs separated by commas
struct pair_struct{
   string symbol;
   MqlRates rates[];
   bool valid;
};
pair_struct pairs[];
bool initial;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit (){
   
   int i= 0 , j= 0 , c;
   string _pairs[], msg= "" ;
   bool pairok= false ;
   initial = true ;
   ENUM_INIT_RETCODE result = INIT_SUCCEEDED ;
   
   StringSplit (UsePairs, StringGetCharacter ( "," , 0 ), _pairs);
   
   for ( i= 0 ; i< ArraySize (_pairs); i++){
      pairok= false ;
      
       for ( j= 0 ; j< SymbolsTotal ( true ); j++){
         if ( SymbolName (j, true ) == _pairs[i] ){
            pairok= true ;
             break ;
         }
      }
       if ( pairok ){
         c= ArraySize (pairs);
         ArrayResize (pairs, c+ 1 );
         pairs[c].symbol = _pairs[i];
         pairs[c].valid = false ;
      } else {
         msg += _pairs[i] + ", " ;
      }
   }
   if ( msg != "" ){
       string invalids = ArraySize (pairs)== 1 ? "Invalid Pair: " : "Invalid Pairs: " ;
      msg = invalids +   StringSubstr (msg, 0 , StringLen (msg)- 2 ) + ". Please Check!" ;
       Alert (msg);
      result = INIT_PARAMETERS_INCORRECT ;
   }
   return (result);

}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit ( const int reason){
   
   Comment ( "" );
   
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate ( const int rates_total,
                 const int prev_calculated,
                 const datetime &time[],
                 const double &open[],
                 const double &high[],
                 const double &low[],
                 const double &close[],
                 const long &tick_volume[],
                 const long &volume[],
                 const int &spread[])
  {

   InitializeRates();
   
   int i= 0 ;
   string log = "" ;
   for (i= 0 ; i< ArraySize (pairs); i++){
       log += "\nPar: " + pairs[i].symbol;
       if ( pairs[i].valid ){
         log += " - Time: " + TimeToString ( pairs[i].rates[ 0 ].time ) + 
                 " - Open: " + DoubleToString ( pairs[i].rates[ 0 ].open, ( int )MarketInfo( pairs[i].symbol, MODE_DIGITS ) ) +
                 " - Close: " + DoubleToString ( pairs[i].rates[ 0 ].close, ( int )MarketInfo( pairs[i].symbol, MODE_DIGITS ) ) +
                 " - High: " + DoubleToString ( pairs[i].rates[ 0 ].high, ( int )MarketInfo( pairs[i].symbol, MODE_DIGITS ) ) +
                 " - Low: " + DoubleToString ( pairs[i].rates[ 0 ].low, ( int )MarketInfo( pairs[i].symbol, MODE_DIGITS ) );
      } else {
         log += " - Currently not valid!" ;
      }
   }

   Comment ( "\n\n*** Pair Rates***\n" + log );
   return (rates_total);
   
}
//+------------------------------------------------------------------+

void InitializeRates(){
 
   for ( int i= 0 ; i< ArraySize ( pairs ); i++ ){
      pairs[i].valid = false ;
       ResetLastError ();
       if ( ArrayCopyRates(pairs[i].rates, pairs[i].symbol, PERIOD_CURRENT ) > 0 ){
         if ( _LastError == 0 ){
             if ( ArraySize (pairs[i].rates) > 0 ){
               if ( pairs[i].rates[ 0 ].time > 0 )
                  pairs[i].valid = true ;
            }
         }
      }
   }

}