라이브러리: 전문가 - 페이지 13

 
fxsaber #:

문제가 있는 경우 재생할 수 있는 mq5 파일을 준비해 주세요.

#define  MT4ORDERS_LIBRARY
#include "../../utils/MT4Orders.mqh" 
// #define REPORT_BROWSER // 브라우저 시작과 함께 보고서 생성 - DLL 권한이 필요합니다.
#define  TESTER_CUSTOM // 사용자 테스터에서 전문가 어드바이저 실행하기
#include "../../utils/fxsaber/Tester/Tester.mqh" // https://www.mql5.com/ko/code/24848

#define  Bid SymbolInfoDouble(_Symbol, SYMBOL_BID)
#define  Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK)

#define  KEY_B 66
#define  KEY_S 83
#define  KEY_C 67

input int In1 = 1;
input group "label1"
input double In2 = 2.0;
// 
void OnChartEvent( const int id, const long &lparam, const double &dparam, const string &sparam ) {
  if (id == CHARTEVENT_KEYDOWN) {
    switch ((int)lparam) {
    case KEY_B: // 구매
      OrderSend(_Symbol, OP_BUY, 1, Ask, 100, 0, 0);
      break;
    case KEY_S: // 판매
      OrderSend(_Symbol, OP_SELL, 1, Bid, 100, 0, 0);
      break;
    case KEY_C: // 닫기
      for (int i = OrdersTotal() - 1; i >= 0; i--)
        if (OrderSelect(i, SELECT_BY_POS) && (OrderType() <= OP_SELL))
          OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 100);
    }
  }
}


void OnTick() {
  //인쇄(_심볼, " ", SymbolInfoDouble(_심볼, SYMBOL_TRADE_TICK_SIZE));
}
void OnTimer() { Comment(REPORT::OrdersToString(_Symbol, 0, 5)); /* */ }
int OnInit() {
  Print(_Symbol, " ", SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE));
  Print(_Symbol, " In2 = ", In2);
  return(INIT_SUCCEEDED);
}
//
void OnDeinit( const int ) {}
//
void OnTradeTransaction(const MqlTradeTransaction& trans, const MqlTradeRequest& request, const MqlTradeResult& result) {

}
//+------------------------------------------------------------------+

샘플 코드는 테스터 라이브러리의 코드를 사용합니다. 시작 후 변수 In2는 2가 아닌 0입니다. 즉, 그룹 이후에는 모든 입력 파라미터를 검색할 수 없습니다.
 
hini #:

이 상황은 고려되지 않은 것 같습니다. 매개 변수가 그룹인 경우 특정 값이 없고 얻은 값이 null이 되므로 그룹 뒤에 오는 매개 변수는 얻지 못합니다.

다음 코드는 모든 것이 올바르게 처리되었음을 보여줍니다.

input int In1 = 1;
input group "label1"
input double In2 = 2.0;

#include <fxsaber\Expert.mqh> // https://www.mql5.com/ko/code/19003

int GetAmountExperts()
{
  int Res = 0;
  
  for (long Chart = ChartFirst(); Chart != -1; Chart = ChartNext(Chart))
    Res += (ChartGetString(Chart, CHART_EXPERT_NAME) != "");
    
  return(Res);
}

void OnInit()
{
  if (GetAmountExperts() < 2)
  {
    MqlParam Params[];
    string Names[];
            
    const int Size = EXPERT::Parameters(0, Params, Names) - 1;
    
    ArrayPrint(Params);
    ArrayPrint(Names);
    
    for (uint i = Size; (bool)i--;)
      EXPERT::AddInputName(Params[i + 1], Names[i]);
            
    Params[Size].string_value = "7";
    EXPERT::Run(ChartOpen(_Symbol, _Period), Params);
  }
}


결과.

    [type] [integer_value] [double_value]      [string_value]
[0]     14               0           0.00 "Scripts\Test6.ex5"
[1]     14               1           1.00 "1"                
[2]     14               0           0.00 null               
[3]     14               2           2.00 "2.0"              
"In1" null  "In2"


Expert.mqh를 통해 Expert Advisor가 시작되었습니다.

 
input bool InRun = true;
input group "label1"
input double In2 = 2.0;

#include <fxsaber\Expert.mqh> // https://www.mql5.com/ko/code/19003


int GetAmountExperts()
{
  int Res = 0;
  
  for (long Chart = ChartFirst(); Chart != -1; Chart = ChartNext(Chart))
    Res += (ChartGetString(Chart, CHART_EXPERT_NAME) != "");
    
  return(Res);
}

void OnInit()
{
  if (InRun)
  {
    MqlParam Params[];
    string Names[];
            
    const int Size = EXPERT::Parameters(0, Params, Names) - 1;
    
    ArrayPrint(Params);
    ArrayPrint(Names);
    int nameSize = ArraySize(Names);
    for (int i = nameSize-1; i >= 0; i--) {
      if (Names[i] == "InRun")
        Params[i+1].string_value = "false";
      EXPERT::AddInputName(Params[i + 1], Names[i]);
    }  
            
    ArrayPrint(Params);
    ArrayPrint(Names);
    //Params[Size].string_value = "7";
    EXPERT::Run(ChartOpen(_Symbol, _Period), Params);
    return;
  }
  Print("In2 = ", In2);
}

알 수 없는 이유로 GetAmountExperts 함수가 매우 오랫동안 결과 없이 실행됩니다. 코드를 약간 변경했으니 다시 실행해 보세요. In2 매개 변수에 값 7을 할당해서는 안 됩니다(2가 아닌 0이 표시됩니다).


 
hini #:

코드가 약간 변경되었으니 다시 실행해 보세요.

이것은 모범적인 버그 신고입니다. 간결한 코드를 실행하니 버그가 즉시 표시되었습니다.

수정했습니다, 감사합니다.

 
fxsaber #:

이것은 모범적인 버그 신고 사례입니다. 간결한 코드를 실행하여 즉시 버그를 발견했습니다.

수정했습니다. 감사합니다.

알겠습니다, 문제가 발생하면 같은 형식으로 보고서를 작성하겠습니다.
 

스크립트가 로드되면 입력 매개변수를 변경할 수 없는 것처럼 보입니다.

 //Test1.ex5
#property script_show_inputs
input string str = "test1" ;
//void OnInit() {
void OnStart () {
   Print (str);
}
 // 지정된 입력 파라미터로 Expert Advisor 시작하기
#property script_show_inputs

#include "Expert.mqh"

input bool CurrentChart = false ; // 현재(true)/새(false) 차트에서 EA 실행하기

string GetMyName( void ) {
   return ( StringSubstr ( MQLInfoString ( MQL_PROGRAM_PATH ), StringLen ( TerminalInfoString ( TERMINAL_DATA_PATH ) + "\\MQL5\\" )));
}

bool RunExpert( const long Chart ) {
   MqlParam Params[ 2 ];
  Params[ 0 ].string_value = "Experts\\Advisors\\Test1.ex5" ;
   // 전문가 어드바이저의 첫 번째 입력 파라미터입니다.
  Params[ 1 ].type = TYPE_STRING ;
  Params[ 1 ].string_value = "Hello World!" ;
   return (EXPERT::Run(Chart, Params));
}

#define  NAME __FILE__

void OnStart () {
   union UNION {
     double Double;
     long Long;
  } Chart;
   if (CurrentChart) {
    Chart.Long = ChartID ();
     GlobalVariableSet (NAME, Chart.Double);
     MqlParam Params[ 1 ];
     // 셀프 경로(스크립트)
    Params[ 0 ].string_value = GetMyName();
     // 새 차트에서 다음과 같이 시작합니다.
    EXPERT::Run( ChartOpen ( _Symbol , _Period ), Params);
  } else if ( GlobalVariableCheck (NAME)) {
    Chart.Double = GlobalVariableGet (NAME);
     GlobalVariableDel (NAME);
    RunExpert(Chart.Long);
     ChartClose ();
  } else // 기본값이 아닌 매개 변수를 사용하여 전문가 조언자를 실행하는 가장 쉬운 방법은 현재 차트에 없습니다.
    RunExpert( ChartOpen ( _Symbol , _Period ));
}
//+------------------------------------------------------------------+
 
hini #:

스크립트가 로드되면 입력 매개변수를 변경할 수 없는 것처럼 보입니다.

스크립트에 대한 입력 매개변수 값을 설정할 수 없고 읽을 수도 없는 것이 MT5의 아키텍처입니다.

라이브러리에는 설득력 있는 이름이 있습니다.

 
fxsaber #:

MT5의 구조상 스크립트에 대한 입력 매개변수 값을 설정할 수 없고 읽을 수도 없습니다.

이 라이브러리에는 설득력 있는 이름이 있습니다.

ok
 
최적화 간격을 설정하지 않고 최적화가 시작될 때 프레임 모드에 대해 자세히 설명합니다.
#include <fxsaber\Expert.mqh> // https://www.mql5.com/ko/code/19003

input group "Params"
input int inRange1 = 0;
input double inRange2 = 0;

// 최적화 간격이 설정되어 있는지 확인합니다.
bool OptimizationIsCorrect()
{
  bool Res = false;
  
  if (MQLInfoInteger(MQL_FRAME_MODE))
  {    
    MqlParam Parameters[];
    string Names[];

    EXPERT::Parameters(0, Parameters, Names);
  
    for (uint i = ArraySize(Names); !Res && (bool)i--;)
    {
      long S[4];
      
      ParameterGetRange(Names[i], Res, S[0], S[1], S[2], S[3]);
    }
  }
      
  return(Res);
}

void OnTesterInit()
{
  if (!OptimizationIsCorrect())
  {
    Alert("no optimized parameter selected, please check input(s) to be optimized and set start, step and stop values");
    
    ChartClose();
  }
}

void OnTesterDeinit() {}
이러한 솔루션이 없으면 프레임 모드의 전문가 어드바이저는 차트에 계속 매달려 있습니다. 이는 테스터를 자동화할 때 특히 중요합니다.