MQL4 및 MQL5에 대한 초보자 질문, 알고리즘 및 코드에 대한 도움말 및 토론 - 페이지 380

 
안녕하세요.
포럼에서 처음으로 포럼에서 엉뚱한 행동을 했다면 미리 사과드립니다.
오랫동안 지표가 있는 차트를 보고 있습니다. 최근에 2개의 예금을 병합했습니다. 새 계좌를 개설하기 전에 히스토리에서 전략의 수익성을 확인하고 싶습니다. MT4의 데모 계정에서.
저는 전혀 프로그래머가 아닙니다. MT4에만 타사 표시기를 설치할 수 있으며 MetaEditor에서 표시기 선 두께를 변경할 수 있습니다(대부분 표시기 코드의 색상은 터미널에서만 변경할 수 없을 것입니다).
알려주십시오. inf. 내 지식을 가진 사람이 어디에서 단계별 테스트를 시작해야 할까요?(구어체로 "흑인을 위한 화장실 사용법 지시")? 전략에는 MA(3개는 단순), Stochastic(표준 수준) 및 CCI(5개 수준)의 3가지 지표가 있습니다. 지표 수준을 위에서 아래로 교차한 후 짧은 거래를 열고 긴 거래 - 그 반대의 경우도 마찬가지입니다(아마도 이해할 수 있습니다..). 테이크 앤 무스 설치.
자동 모드에서 전략의 작동을 시각적으로 추적하고 지표 및 주문의 매개변수를 선택하기 위해 시각화 없이 모두 추적할 수 있기를 바랍니다.
 
ZebStamp :
안녕하세요.
포럼에서 처음으로 포럼에서 엉뚱한 행동을 했다면 미리 사과드립니다.
오랫동안 지표가 있는 차트를 보고 있습니다. 최근에 2개의 예금을 병합했습니다. 새 계좌를 개설하기 전에 히스토리에서 전략의 수익성을 확인하고 싶습니다. MT4의 데모 계정에서.
저는 전혀 프로그래머가 아닙니다. MT4에만 타사 표시기를 설치할 수 있으며 MetaEditor에서 표시기 선 두께를 변경할 수 있습니다(대부분 표시기 코드의 색상은 터미널에서만 변경할 수 없을 것입니다).
알려주십시오. inf. 내 지식을 가진 사람이 어디에서 단계별 테스트를 시작해야 할까요?(구어체로 "흑인을 위한 화장실 사용법 지시")? 전략에는 MA(3개는 단순), Stochastic(표준 수준) 및 CCI(5개 수준)의 3가지 지표가 있습니다. 지표 수준을 위에서 아래로 교차한 후 짧은 거래를 열고 긴 거래 - 그 반대의 경우도 마찬가지입니다(아마도 이해할 수 있습니다..). 테이크 앤 무스 설치.
자동 모드에서 전략의 작동을 시각적으로 추적하고 지표 및 주문의 매개변수를 선택하기 위해 시각화 없이 모두 추적할 수 있기를 바랍니다.

TrendLine과 같은 그래픽 개체(GO)를 생성할 때 색상을 선택하십시오. TrendLine을 다시 생성할 때 동일한 색상으로 생성됩니다. Hline의 경우 색상을 선택했으며 다음 색상도 마찬가지입니다. 노란색, 파란색, ...

GO가 어드바이저, 인디케이터, 스크립트를 생성하는 경우 프로그램에 작성하는 방법. 때때로 매개변수 선택

 
STARIJ :

코드를 보고 있는 누군가가 오류를 빠르게 찾을 수 있다고 생각한다면 오산입니다. 컴파일러는 오류를 찾습니다. 프로그램의 텍스트는 포맷되어야 합니다 - MetaEditor에는 이를 위한 스타일러 가 있습니다. 다른 스타일을 좋아한다면 예를 들어 AStyle.exe 프로그램을 사용하십시오. 스타일을 지정하고 나면 프로그램 1)에 추가 닫는 중괄호가 있음을 빠르게 알 수 있습니다. 2) 선언된 변수: datetime date_Buf_1; // 표시기 날짜의 배열 - 배열로 만들려면 동적 배열 에 대해 [크기] 또는 []가 필요하고 크기를 ArrayResize로 설정해야 합니다. 그리고 이것은 배열을 사용하기 전에 수행되어야 합니다. 이에 대한 위의 게시물을 참조하십시오. 3) FileOpen(InpDirectoryName+"//"+InpFileName - 스틱을 다른 방향으로 기울일 필요가 있는 것 같습니다. InpDirectoryName+"//" 없이 하는 것이 좋습니다. - Files 폴더에서 파일을 찾을 수 있습니다.

줄당: int copy=CopyTime(NULL,0,0,0,date_Buf_1); 컴파일러 화가, 시작=종료=0 횟수=0


고맙습니다. 뭔가 수정되었지만 이해보다 직관적으로 밝혀졌습니다. 그러나 어레이와 관련하여 모두 동일하게 3개의 오류가 발생합니다.

'Buf_1' - 배열 필요 111.mq4 93 21

'date_Buf_1' - 배열 필수 111.mq4 94 21

'Buf_1' - 배열 필요 111.mq4 100 열여섯


 //+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
input string              InpFileName= "111.csv" ;       // Имя файла 
input string              InpDirectoryName= "Data" ;     // Имя каталога 

datetime Время= 0 ;   // Время прошлого бара
double Bid1;
double    Buf_1[];
// double ExtBuffer;
long V1; // объем для текущего тика вверх
long V2; // накопленный объем для всех тиков вверх текущего бара
long V3; // объем текущего тика вниз
long V4; // накопленный объем для всех тиков вниз для текущего бара
long V5;   // отрицательные и положительные iVolume нарастающим итогом
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnInit ()
  {
   IndicatorDigits ( 0 );
   SetIndexBuffer ( 0 ,Buf_1);
//SetIndexBuffer(1,Buf_2);
   Bid1= Bid ;
   V5= 0 ;

  }
//+------------------------------------------------------------------+
//| 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[])
  {
   datetime Вр= Time [ 0 ];   // Время текущего бара
   if (Вр>Время)           // Если новый бар
     {
      Время=Вр;           // Запомнить
                           //      Buf_1[0]=0;         // и обнулить последний элемент буфера
     }

   datetime date_Buf_1[]; // массив дат индикатора 
   datetime time_Buf_1[]; // массив времени 
                           // --- считаю объем для положительных и отрицательных тиков      
   if ( Bid >=Bid1)
     {
       if ( Bid >Bid1) // если тик положительный..
        {
         V1= iVolume ( NULL , 0 , 0 ); // если повышающий цену тик, то находим его объем
         V2= V1 + V2;
        }
       else
        {
         V1= 0 ;                 // если Bid1 = Bid2, т.е. изменение цены = 0, то iVolume этого тика присваиваем 0;
         V2= V1 + V2;
        }
     }
   else
     {
      V3 = iVolume ( NULL , 0 , 0 ); // если понижающий цену тик 
      V4 = V3 + V4;             // то находим его объем  
     }

   V5=V2-V4;               // определяем разницу (дельту) между объемами положительных и отрицательных тиков
   Bid1= Bid ;
   Buf_1[ 0 ]=V5; // в буфер сгружаем  дельту

                 //   ExtBuffer = Buf_1 [0];
//   double macurrent=iMAOnArray(ExtBuffer,0,5,0,MODE_LWMA,0); 

// запись в файл данных буфера


//--- установим для массивов признак таймсерии 
   ArraySetAsSeries (Buf_1[ 0 ], true );
   ArraySetAsSeries (date_Buf_1[ 0 ], true );

//--- скопируем таймсерию 
   int copied= CopyTime ( NULL , 0 , 10000 , 0 ,date_Buf_1);

//--- подготовим массив Buf_1 
   ArrayResize (Buf_1[ 0 ],copied);

//--- скопируем значения линии индикатора  
   for ( int i= 0 ;i<copied;i++)
     {
      Buf_1[i]=V5;
     }
//--- откроем файл для записи значений индикатора 
   ResetLastError ();
   int file_handle= FileOpen (InpDirectoryName+ "//" +InpFileName, FILE_READ | FILE_WRITE | FILE_CSV );
   if (file_handle!= INVALID_HANDLE )
     {
       PrintFormat ( "Файл %s открыт для записи" ,InpFileName);
       PrintFormat ( "Путь к файлу: %s\\Files\\" , TerminalInfoString ( TERMINAL_DATA_PATH ));
       //--- сначала запишем значения индикатора 
       FileWrite (file_handle,Buf_1[ 0 ]);
       //--- запишем время и значения в файл 
       for ( int i= 0 ;i<Buf_1[ 0 ];i++)
         FileWrite (file_handle,time_Buf_1[ 0 ],Buf_1[ 0 ]);
       //--- закрываем файл 
       FileClose (file_handle);
       PrintFormat ( "Данные записаны, файл %s закрыт" ,InpFileName);
     }
   else
       PrintFormat ( "Не удалось открыть файл %s, Код ошибки = %d" ,InpFileName, GetLastError ());

   return (rates_total);
  }
//+------------------------------------------------------------------+


귀하의 의견을 구현하는 방법을 이해하지 못했습니다. 하지만 추가 브래킷을 찾았습니다 :)
 
YarTrade :

고맙습니다. 뭔가 수정되었지만 이해보다 직관적으로 밝혀졌습니다. 그러나 어레이와 관련하여 모두 동일하게 3개의 오류가 발생합니다.

'Buf_1' - 배열 필요 111.mq4 93 21

'date_Buf_1' - 배열 필수 111.mq4 94 21

'Buf_1' - 배열 필요 111.mq4 100 열여섯



귀하의 의견을 구현하는 방법을 이해하지 못했습니다. 하지만 추가 브래킷을 찾았습니다 :)
배열 변수의 이름만 남겨두십시오. 컴파일러가 가리키는 코드 줄에서 "[]"를 제거하십시오.
 
Artyom Trishkin :
배열 변수의 이름만 남겨두십시오. 컴파일러가 가리키는 코드 줄에서 "[]"를 제거하십시오.

고맙습니다. 나는 내 인생에서 무슨 일이 일어 났는지 볼 것입니다. 뭔가 파일에 뭔가가 쓰여질 것 같아 큰 의심이 듭니다. :)

 

많은 질문이 생겼습니다. 정말 도움이 되기를 바랍니다. 테스트 중 어드바이저와 실시간으로 하는 일이 많이 다르다는 안타까운 점을 발견하여 가장 흔하고 대표적인 오류를 분석해보려고 합니다. 먼저, 내가 겪은 일을 쓸 것입니다. 지식이 있는 사람들도 그들의 경험을 공유하면 좋을 것입니다. 잊지 말아야 할 것과 코드에 있어야 하는 것.

1. 실제 거래 모드에서 0으로 나누기 오류가 발생했지만 물론 코드에 0으로 나누기가 없었고 백테스트 중에 나타나지 않았습니다. 각 제수를 NormalizeDouble(x,Digits);

2. 거래가 열리지 않았습니다. 금요일에 백테스트를 거친 후 거래가 열렸지만 실제 거래 중에는 그렇지 않았습니다. 고문의 로그에서 오류가 발생하지 않았습니다. 여기서 나는 문제가 무엇인지 모르지만 몇 가지에 대해 죄를 지었습니다. 첫째, "'ordersend'의 반환 값을 확인해야 합니다"와 같은 경고가 있지만 올바르게 이해하면 코드 실행에 영향을 미치지 않아야 합니까? 아니면 미끄러짐에 관한 모든 것입니까? 나는 1을 가지고 있는데 아주 작지는 않은 것 같다. 그리고 입구가 열려야 했던 바가 틈 없이 열렸다.

3. 표준 슬라이더 예제에서 "if(Volume[0]>1) return;" 코드 시작 부분에 붙여넣습니다. 즉, 내 코드는 새 막대가 나타날 때 첫 번째 틱 동안에만 실행됩니다. 볼륨과 함께 막대가 즉시 열리고 내 코드가 실행되지 않을 수 있습니까?

4. 히스토리와 리얼타임으로 어드바이저와 작업할 때 주의할 점이나 전형적인 실수를 조언해주세요


 
LuckySith :

많은 질문이 생겼습니다. 정말 도움이 되기를 바랍니다. 테스트 중 어드바이저와 실시간으로 하는 일이 많이 다르다는 안타까운 점을 발견하여 가장 흔하고 대표적인 오류를 분석해보려고 합니다. 먼저, 내가 겪은 일을 쓸 것입니다. 지식이 있는 사람들도 그들의 경험을 공유하면 좋을 것입니다. 잊지 말아야 할 것과 코드에 있어야 하는 것.

1. 실제 거래 모드에서 0으로 나누기 오류가 발생했지만 물론 코드에 0으로 나누기가 없었고 백테스트 중에 나타나지 않았습니다. 각 제수를 NormalizeDouble(x,Digits);

2. 거래가 열리지 않았습니다. 금요일 백테스트에서 거래를 취소한 후 거래가 열렸지만 실제 거래 중에는 그렇지 않았습니다. 고문의 로그에서 오류가 발생하지 않았습니다. 여기서 나는 문제가 무엇인지 모르지만 몇 가지에 대해 죄를 지었습니다. 첫째, "'ordersend'의 반환 값을 확인해야 합니다"와 같은 경고가 있지만 올바르게 이해하면 코드 실행에 영향을 미치지 않아야 합니까? 아니면 미끄러짐에 관한 모든 것입니까? 나는 1을 가지고 있는데 아주 작지는 않은 것 같다. 그리고 입구가 열려야 했던 바가 틈 없이 열렸다.

3. 표준 슬라이더 예제에서 "if(Volume[0]>1) return;" 코드 시작 부분에 붙여넣습니다. 즉, 내 코드는 새 막대가 나타날 때 첫 번째 틱 동안에만 실행됩니다. 볼륨과 함께 막대가 즉시 열리고 내 코드가 실행되지 않을 수 있습니까?

4. 히스토리와 리얼타임으로 어드바이저와 일할 때 주의할 점이나 전형적인 실수를 조언해주세요

이러한 야생 구조를 "if(Volume[0]>1) return;"으로 바꿉니다. "New Bar"의 정상적인 확인을 위해 여기 포럼에 많은 것이 있습니다.

"'ordersend'의 반환 값을 확인해야 합니다"와 같은 경고는 아직 버그가 아니지만 향후 잠재적인 버그입니다. 코드에는 경고가 없어야 하며, 온라인으로 작업할 때는 더욱 그렇습니다.

"나는 1을 가지고 있는데 아주 작지 않은 것 같다." - 이것은 새로운 바를 열 때 매우 작을 수 있으며, 이 시점에서 30분, 1시간마다 스프레드가 크게 확장됩니다.

필요한 것: 새 바를 확인하고 새 바가 있으면 진입 조건을 살펴보고 일치하면 거래를 성사시키십시오. 그 후에 막대가 해결되었다고 기록하고 새로운 막대를 기다리고 있습니다.

현재 상황: if(Volume[0]>1) return; = 새 막대인 경우 조건을 살펴보고 조건이 맞지 않음 == 큰 스프레드 = OnTick()에서 다시 종료, 다음 틱에서 if(Volume[0]>1) return; 더 이상 놓치지 않으므로 스프레드가 0.0001이더라도 거래를 건너뜁니다.

 

안녕하세요. 코드를 사용하여 다음을 어떻게 설명할 수 있는지 알려주십시오. 위쪽 및 아래쪽 수평선 에 의해 제한된 평면이 있습니다. 그들의 고문이 스스로 결정하고 설치합니다.

어드바이저는 플랫 존에서 가격 출구를 결정한 다음 이 존으로 돌아오는 것이 필요합니다. 그리고 나서야 그는 포지션을 열었습니다.

노이즈를 필터링하기 위해 매개변수가 2 또는 3인 이동 평균을 사용합니다.

 
Vitaly Muzichenko :

이러한 야생 구조를 "if(Volume[0]>1) return;"으로 바꿉니다. "New Bar"에 대한 일반적인 확인을 위해 여기 포럼에 많은 것이 있습니다.

"'ordersend'의 반환 값을 확인해야 합니다"와 같은 경고는 아직 버그가 아니지만 향후 잠재적인 버그입니다. 코드에는 경고가 없어야 하며, 온라인으로 작업할 때는 더욱 그렇습니다.

"나는 1을 가지고 있는데 아주 작지 않은 것 같다." - 이것은 새로운 바를 열 때 매우 작을 수 있으며, 이 시점에서 30분, 1시간마다 스프레드가 크게 확장됩니다.

필요한 것: 새 바를 확인하고 새 바가 있으면 진입 조건을 살펴보고 일치하면 거래를 성사시키십시오. 그런 다음 막대가 해결되었다고 기록하고 새로운 막대를 기다리고 있습니다.

현재 상황: if(Volume[0]>1) return; = 새 막대인 경우 조건을 살펴보고 조건이 맞지 않음 == 큰 스프레드 = OnTick()에서 다시 종료, 다음 틱에서 if(Volume[0]>1) return; 더 이상 놓치지 않으므로 스프레드가 0.0001이더라도 거래를 건너뜁니다.


새로운 바를 여는 방법에 대해 . 좋은 선택이 될까요? :

 datetime counted_bar = 0 ;

int OnInit ()
{
   counted_bar = 0 ; // если нужно, чтоб при перезапуске последний бар был проанализирован
   ...

void OnTick ()
{
   // Если появился новый бар
   if ( iTime ( _Symbol , _Period , 0 ) > counted_bar )
   {
      counted_bar = iTime ( _Symbol , _Period , 0 );

       // Анализируем индикаторы
      ...
   }
 
LuckySith :

새로운 바를 여는 방법에 대해 . 좋은 선택이 될까요? :

처음에는 이대로 두십시오.

다음으로, 막대가 해결되었음을 올바르게 고정해야 하지만 여기에서는 TK에 대한 전체 접근 방식을 계산해야 합니다.

지금까지 귀하의 게시물에서 본 것을 보면 다음을 수행해야 합니다.

 void OnTick ()
{
   // Если появился новый бар
   if ( iTime ( _Symbol , _Period , 0 ) > counted_bar )
   {
       // Анализируем индикаторы
       if (SpreadMax > текущий спред) return ;

      counted_bar = iTime ( _Symbol , _Period , 0 );
      ...
   }

결론은 스프레드가 표준보다 크면 OnTick 으로 돌아가고 새 틱에서 스프레드를 확인하고 정상이면 주문을 보내고 이 막대에 거래가 있었음을 기억한다는 것입니다. .

두 번째 방법도 있습니다.

 void OnTick ()
{
   // Если появился новый бар
   if ( iTime ( _Symbol , _Period , 0 ) > counted_bar )
   {
       if (SpreadMax > текущий спред) return ;
       // Анализируем индикаторы
      ...
      result = OrderSend (...);
       // если открылась позиция, то result будет тикет позиции
       if (result> 0 ) counted_bar = iTime ( _Symbol , _Period , 0 );
   }

일반적으로 언제 기록해야 하는지 논리를 결정해야 하며 "새 막대"가 형성되기 전에 더 이상 확인하지 않습니다.