포럼을 어지럽히 지 않도록 모든 초보자 질문. 프로, 놓치지 마세요. 너 없이는 아무데도 - 6. - 페이지 342

 

여기 프로젝트의 .cpp 파일이 있습니다. 이 파일을 보고 Google과 Yandex를 몇 번 가보겠습니다. 머리를 깨는 어떤 것도 발견하지 못했습니다. 전체적으로 이해할 수 있습니다. 심지어 간단해 보입니다.

 //+------------------------------------------------------------------+
//| Sample DLL for MQL4 |
//| Copyright 2001-2012, MetaQuotes Software Corp. |
//| http://www.metaquotes.net |
//+------------------------------------------------------------------+
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
//---
#define MT4_EXPFUNC __declspec(dllexport) //это что?
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#pragma pack(push, 1 )
struct RateInfo // Структура, переменные
{
unsigned int ctm;
double open;
double low;
double high;
double close;
double vol;
};
#pragma pack(pop)
//---
struct MqlStr
{
int len;
char * string // Указатель на стринг, я плохо помню.
};
static int CompareMqlStr( const void *left, const void *right);
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved) //функция 
{
//---
switch (ul_reason_for_call) // оператор что делать
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH: //что это всюду, не понял.
break ;
}
//---
return (TRUE);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC int __stdcall GetIntValue( const int ipar) // __stdcall кладет аргументы в стек справа налево
{ // MT4_EXPFUNC говорит что функция будет видима из метатрайдера, я не совсем понял.
printf ( "GetIntValue takes %d\n" ,ipar);
return (ipar);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC double __stdcall GetDoubleValue( const double dpar)
{
printf ( "GetDoubleValue takes %.8lf\n" ,dpar);
return (dpar);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC char * __stdcall GetStringValue( char *spar)
{
printf ( "GetDoubleValue takes \"%s\"\n" ,spar);
return (spar);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC double __stdcall GetArrayItemValue( const double *arr, const int arraysize, const int nitem)
{
//---
if (arr== NULL )
{
printf ( "GetArrayItemValue: NULL array\n" );
return ( 0.0 );
}
if (arraysize<= 0 )
{
printf ( "GetArrayItemValue: wrong arraysize (%d)\n" , arraysize);
return ( 0.0 );
}
if (nitem< 0 || nitem>=arraysize)
{
printf ( "GetArrayItemValue: wrong item number (%d)\n" , nitem);
return ( 0.0 );
}
//---
return (arr[nitem]);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC BOOL __stdcall SetArrayItemValue( double *arr, const int arraysize, const int nitem, const double value)
{
//---
if (arr== NULL )
{
printf ( "GetArrayItemValue: NULL array\n" );
return (FALSE);
}
if (arraysize<= 0 )
{
printf ( "GetArrayItemValue: wrong arraysize (%d)\n" , arraysize);
return (FALSE);
}
if (nitem< 0 || nitem>=arraysize)
{
printf ( "GetArrayItemValue: wrong item number (%d)\n" , nitem);
return (FALSE);
}
//---
arr[nitem]=value;
return (TRUE);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC double __stdcall GetRatesItemValue( const RateInfo* rates, const int rates_total, const int shift, const int nrate)
{
//---
if (rates== NULL )
{
printf ( "GetRatesItemValue: NULL array\n" );
return ( 0.0 );
}
//---
if (rates_total< 0 )
{
printf ( "GetRatesItemValue: wrong rates_total number (%d)\n" , rates_total);
return ( 0.0 );
}
//---
if (shift< 0 || shift>=rates_total)
{
printf ( "GetRatesItemValue: wrong shift number (%d)\n" , shift);
return ( 0.0 );
}
//---
if (nrate< 0 || nrate> 5 )
{
printf ( "GetRatesItemValue: wrong rate index (%d)\n" , nrate);
return ( 0.0 );
}
//---
int nitem=rates_total- 1 -shift;
switch (nrate)
{
case 0 : return double (rates[nitem].ctm);
case 1 : return rates[nitem].open;
case 2 : return rates[nitem].low;
case 3 : return rates[nitem].high;
case 4 : return rates[nitem].close;
case 5 : return rates[nitem].vol;
}
//---
return ( 0.0 );
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC int __stdcall SortStringArray(MqlStr *arr, const int arraysize)
{
//---
if (arr== NULL )
{
printf ( "SortStringArray: NULL array\n" );
return (- 1 );
}
if (arraysize<= 0 )
{
printf ( "SortStringArray: wrong arraysize (%d)\n" , arraysize);
return (- 1 );
}
//---
qsort(arr,arraysize, sizeof (MqlStr),CompareMqlStr);
//---
return (arraysize);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC int __stdcall ProcessStringArray(MqlStr *arr, const int arraysize)
{
int len1,len2;
//---
if (arr== NULL )
{
printf ( "ProcessStringArray: NULL array\n" );
return (- 1 );
}
if (arraysize<= 0 )
{
printf ( "ProcessStringArray: wrong arraysize (%d)\n" , arraysize);
return (- 1 );
}
//---
for ( int i= 0 ; i<arraysize- 1 ; i++)
{
if (arr[i]. string == NULL ) len1= 0 ;
else len1=strlen(arr[i]. string );
if (arr[i+ 1 ]. string == NULL ) len2= 0 ;
else len2=strlen(arr[i+ 1 ]. string );
//--- uninitialized string
if (arr[i+ 1 ]. string == NULL ) continue ;
//--- destination string is uninitialized and cannot be allocated within dll
if (arr[i]. string == NULL ) continue ;
//--- memory piece is less than needed and cannot be reallocated within dll
if (arr[i].len<len1+len2) continue ;
//--- final processing
strcat(arr[i]. string ,arr[i+ 1 ]. string );
}
//---
return (arraysize);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int CompareMqlStr( const void *left, const void *right)
{
MqlStr *leftstr=(MqlStr *)left;
MqlStr *rightstr=(MqlStr *)right;
//---
if (leftstr-> string == NULL ) return (- 1 ); //-> вот этот знак я не знаю
if (rightstr-> string == NULL ) return ( 1 );
//---
return (strcmp(leftstr-> string ,rightstr-> string ));
}
//+------------------------------------------------------------------+

하지만 어떻게 작동합니까?? EA 코드에서 이 ddl에 액세스하는 방법을 잘 이해하지 못했습니다. 어떻게? 먼저 #include <GetIntValue> 와 같습니다. 아니요, 뭔가 잘못되었습니다..

2. dll을 호출할 때 포함된 스튜디오를 그대로 둘 필요는 없잖아요? 어떻게 수행됩니까?

mql 코드에서 동일한 dll에 액세스하는 가장 간단한 예를 보여주세요.

 
Trader7777 :

여기서 이해가 안되는게..


두 번째 단방향 주문이 열리면 로트 크기가 기하급수적으로 증가해야 합니다(2의 승수로).



이것은 결과입니다

그럼 이렇게

 double OrderLotsSell( string sy= "" , int op=- 1 , int mn=- 1 ) { 
 datetime o;
   int       i, k= OrdersTotal (); double r=- 1 ;

   if (sy== "0" ) sy= Symbol ();
   for (i= 0 ; i<k; i++) {
     if ( OrderSelect (i, SELECT_BY_POS, MODE_TRADES)) {
       if (OrderSymbol()==sy || sy== "" ) {
         if ( OrderType()==OP_SELL) {
           if (op< 0 || OrderType()==OP_SELL) {
             if (mn< 0 || OrderMagicNumber()==Magic) {
              r=OrderLots()* 2 ;
            }
          }
        }
      }
    }
  }
   return (r);
}

double OrderLotsBuy( string sy= "" , int op=- 1 , int mn=- 1 ) { 
 datetime o;
   int       i, k= OrdersTotal (); double r=- 1 ;

   if (sy== "0" ) sy= Symbol ();
   for (i= 0 ; i<k; i++) {
     if ( OrderSelect (i, SELECT_BY_POS, MODE_TRADES)) {
       if (OrderSymbol()==sy || sy== "" ) {
         if ( OrderType()==OP_BUY) {
           if (op< 0 || OrderType()==OP_BUY) {
             if (mn< 0 || OrderMagicNumber()==Magic) {
              r=OrderLots()* 2 ;
            }
          }
        }
      }
    }
  }
   return (r);
}





 
max020780 :


이것은 결과입니다

그럼 이렇게


감사합니다. 생각의 기차를 이해했습니다. 더 정확하게 알아 냈습니다.

이 줄은 무엇을 위한 것입니까?


 datetime o;
 

여기 또 다른 질문이 있습니다. 트레일러가 있습니다. 1개의 단방향 주문이 열리면 모든 것이 훌륭하게 작동합니다. 그 이상이면 어떤 이유로 작동하지 않습니다. 왜요?

void Trailing ()
{
for(int i = 0; i<OrdersTotal(); i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
{
if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
{
if (OrderType() == OP_BUY)
{
if(Bid - OrderOpenPrice() > TrailingStop*Point)
{
if (OrderStopLoss() < Bid - (TrailingStop + TrailingStep)*Point)
{
SL = NormalizeDouble(Bid - TrailingStop*Point,Digits);
if (OrderStopLoss() !=SL)
OrderModify(OrderTicket(),OrderOpenPrice(),SL,0,0);
}
}
}
if (OrderType() == OP_SELL)
{
if(OrderOpenPrice() - Ask > TrailingStop*Point)
{
if (OrderStopLoss() > Ask + (TrailingStop+ TrailingStep)*Point)
{
SL = NormalizeDouble (Ask+TrailingStop*Point,Digits);
if (OrderStopLoss() !=SL)
OrderModify (OrderTicket(), OrderOpenPrice(), SL,0,0);
}
}
}
}
}
}
}


 
Vladimirovits :

여기 프로젝트의 .cpp 파일이 있습니다. 이 파일을 보고 Google과 Yandex에 몇 번 가보겠습니다. 머리를 깨는 어떤 것도 발견하지 못했습니다. 전체적으로 이해할 수 있습니다. 심지어 간단해 보입니다.

하지만 어떻게 작동합니까?? EA 코드에서 이 ddl에 액세스하는 방법을 잘 이해하지 못했습니다. 어떻게? 먼저 #include <GetIntValue> 와 같습니다. 아니요, 뭔가 잘못되었습니다..

대략 이렇습니다. 그것을 작동시키려면 DLL을 컴파일하고 그것을 전문가/라이브러리 폴더에 넣어야 합니다(도움말과 튜토리얼을 읽으십시오. 모든 것이 거기에 자세히 설명되어 있습니다).

 //сначала надо объявить импорт функции из DLL
#import "имя_вашей_длл.dll"
int SortStringArray( string *arr[], const int arraysize);
#import


//в тексте программы вызов проще простого

string arr[];
int size;
...
//где-то в коде массив заполняется
...
//а вот и вызов сортировки
SortStringArray(arr,size);

2. dll을 호출할 때 스튜디오를 계속 켜둘 필요는 없잖아요? 어떻게 수행됩니까?

DLL은 간단히 말해서 일반적인 Windows 프로그램입니다. 단, Dll에 구현된 기능은 사용자가 호출하는 것이 아니라 다른 프로그램에서 호출하는 것입니다. 이를 가능하게 하기 위해 C++ 언어 컴파일러에 __declspec(dllexport) 수정자를 지정합니다.
 
Trader7777 :

여기 또 다른 질문이 있습니다. 트레일러가 있어요. 1개의 단방향 주문이 열리면 모든 것이 훌륭하게 작동합니다. 그 이상이면 어떤 이유로 작동하지 않습니다. 왜요?

void Trailing ()
{
for(int i = 0; i<OrdersTotal(); i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
{
if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
{
if (OrderType() == OP_BUY)
{
if(Bid - OrderOpenPrice() > TrailingStop*Point)
{
if (OrderStopLoss() < Bid - (TrailingStop + TrailingStep)*Point)
{
SL = NormalizeDouble(Bid - TrailingStop*Point,Digits);
if (OrderStopLoss() !=SL)
OrderModify(OrderTicket(),OrderOpenPrice(),SL,0,0);
}
}
}
if (OrderType() == OP_SELL)
{
if(OrderOpenPrice() - Ask > TrailingStop*Point)
{
if (OrderStopLoss() > Ask + (TrailingStop+ TrailingStep)*Point)
{
SL = NormalizeDouble (Ask+TrailingStop*Point,Digits);
if (OrderStopLoss() !=SL)
OrderModify (OrderTicket(), OrderOpenPrice(), SL,0,0);
}
}
}
}
}
}
}


함수에 매개변수를 전달해야 하므로 다음을 시도하십시오.

부울 IfProfTrail=거짓; // 수익성 있는 포지션에만 사용 - 손익분기점 모드
int TrailingStop=0; // 후행 거리 = 0 - 최소 허용
int TrailingStep=1; // 거리 스텝


 void Trailing( string sy= "" , int op=- 1 , int mn=- 1 )
  {
   double po,pp;
   int     i,k= OrdersTotal ();
   

   if (sy== "0" ) sy= Symbol ();
   if (TrailingStop== 0 )TrailingStop=MarketInfo( Symbol (),MODE_STOPLEVEL);
   for (i= 0 ;i<k;i++)
     {
       if ( OrderSelect (i,SELECT_BY_POS,MODE_TRADES))
        {
         if ((OrderSymbol()==sy || sy== "" ) && (op< 0 || OrderType()==op))
           {
            po=MarketInfo(OrderSymbol(),MODE_POINT);
             if (mn< 0 || OrderMagicNumber()==mn)
              {
               if (OrderType()==OP_BUY)
                 {
                  pp=MarketInfo(OrderSymbol(),MODE_BID);
                   if ((!IfProfTrail && OrderProfit()> 0 ) || pp-OrderOpenPrice()>TrailingStop*po)
                    {
                     if (OrderStopLoss()<pp-(TrailingStop+TrailingStep- 1 )*po)
                       {
                        ModifyOrder(- 1 ,pp-TrailingStop*po,- 1 );
                       }
                    }
                 }
               if (OrderType()==OP_SELL)
                 {
                  pp=MarketInfo(OrderSymbol(),MODE_ASK);
                   if ((!IfProfTrail && OrderProfit()> 0 ) || OrderOpenPrice()-pp>TrailingStop*po)
                    {
                     if (OrderStopLoss()>pp+(TrailingStop+TrailingStep- 1 )*po || OrderStopLoss()== 0 )
                       {
                        ModifyOrder(- 1 ,pp+TrailingStop*po,- 1 );
                       }
                    }
                 }
              }
           }
        }
     }
  }


 
Forexman77 :

정말 감사합니다!

이제 문제가 무엇인지 명확해졌습니다.

구입에 사용:

내가 아는 한, 구매는 요청에 의해 진행되고 iClose(Symbol(),Period(),0)는 입찰에서 가격을 가져옵니다. 결과적으로 오류가 발생할 가능성이 있습니다.

이제 다음 조합을 사용합니다.

그러나 어드바이저가 핍이 아니기 때문에 가격이 오랫동안 매수 영역에 있었고 매 틱마다 업데이트되기 때문에 즉시 문제가 발생합니다.

거래가 열리지 않는 이유는 무엇입니까? 고문이 오류로 멈추고 더 이상의 가격 변화가 보이지 않는 것으로 나타났습니까?

여기에서 Expert Advisor 템플릿을 가져왔습니다. https://c.mql5.com/mql4/book/mq4/experts/tradingexpert.mq4

이 EA의 오류 처리 기능에 129 및 138 오류에 대한 검사를 추가할 가치가 있다고 생각하십니까?

그렇다면 어떻게 해야 할까요?

최소한 모든 오류를 처리하는 포지션 개설/주문 설정을 위한 고유한 기능이 있어야 합니다. 그것은 당신이 최신 가격을 얻을 필요가 있다는 것입니다.

어떤 빌드도 보지 않았습니다. 그러나 나는 말할 것입니다. Expert Advisor에서 서버에서 반환된 모든 오류를 처리해야 합니다. 그리고 이것으로 충분하지 않습니다. 그는 기능의 손실과 알고리즘의 실패 없이 예측하지 못한 상황이 발생했을 때 자신의 위치를 차지할 수 있어야 하며 특별한 일이 없었던 것처럼 작업을 계속할 수 있어야 합니다.

 
전문가/라이브러리 폴더에 컴파일하여 넣으십시오. 감사합니다!!! 지금 시도하겠습니다. 예전에는 만났지만 지금은 그 주제에 대해 그렇게 상세하고 소화할 수 있는 것을 찾지 못했습니다.
 
artmedia70 :

최소한 모든 오류를 처리하는 포지션 개설/주문 설정을 위한 고유한 기능이 있어야 합니다. 그것은 당신이 최신 가격을 얻을 필요가 있다는 것입니다.

어떤 빌드도 보지 않았습니다. 그러나 나는 말할 것입니다. Expert Advisor에서 서버에서 반환된 모든 오류를 처리해야 합니다. 그리고 이것으로 충분하지 않습니다. 그는 기능의 손실과 알고리즘의 실패 없이 예측하지 못한 상황이 발생했을 때 자신의 위치를 차지할 수 있어야 하며 특별한 일이 없었던 것처럼 작업을 계속할 수 있어야 합니다.


템플릿은 교과서에서 가져왔습니다. 현재 오류 처리 기능이 특히 강력하지 않습니다.

주문을 시작할 때 RefreshRates()가 있습니다. (비딩과 매도는 그들이 말한 대로 시장 정보를 통해 대체됨)

 while ( true )                                   // Цикл закрытия орд.
     {
       if (Total== 0 && Opn_B== true )               // Открытых орд. нет +
        {                                       // критерий откр. Buy
         RefreshRates();                         // Обновление данных
         SL=Bid - New_Stop(StopLoss)* Point ;     // Вычисление SL откр.
         TP=Bid + New_Stop(TakeProfit)* Point ;   // Вычисление TP откр.
         Alert ( "Попытка открыть Buy. Ожидание ответа.." );
         Ticket= OrderSend (Symb,OP_BUY,Lts,Ask, 2 ,SL,TP); //Открытие Buy
         if (Ticket > 0 )                         // Получилось :)
           {
             Alert ( "Открыт ордер Buy " ,Ticket);
             return ;                             // Выход из start()
           }
         if (Fun_Error( GetLastError ())== 1 )       // Обработка ошибок
             continue ;                           // Повторная попытка
         return ;                                 // Выход из start()
        }

그리고 오류 처리 기능:

 int Fun_Error( int Error)                         // Ф-ия обработ ошибок
  {
   switch (Error)
     {                                           // Преодолимые ошибки            
       case    4 : Alert ( "Торговый сервер занят. Пробуем ещё раз.." );
         Sleep ( 3000 );                           // Простое решение
         return ( 1 );                             // Выход из функции
       case 135 : Alert ( "Цена изменилась. Пробуем ещё раз.." );
         RefreshRates();                         // Обновим данные
         return ( 1 );                             // Выход из функции
       case 136 : Alert ( "Нет цен. Ждём новый тик.." );
         while (RefreshRates()== false )           // До нового тика
             Sleep ( 1 );                           // Задержка в цикле
         return ( 1 );                             // Выход из функции
       case 137 : Alert ( "Брокер занят. Пробуем ещё раз.." );
         Sleep ( 3000 );                           // Простое решение
         return ( 1 );                             // Выход из функции
       case 146 : Alert ( "Подсистема торговли занята. Пробуем ещё.." );
         Sleep ( 500 );                             // Простое решение
         return ( 1 );                             // Выход из функции
         // Критические ошибки
       case    2 : Alert ( "Общая ошибка." );
         return ( 0 );                             // Выход из функции
       case    5 : Alert ( "Старая версия терминала." );
         Work= false ;                             // Больше не работать
         return ( 0 );                             // Выход из функции
       case 64 : Alert ( "Счет заблокирован." );
         Work= false ;                             // Больше не работать
         return ( 0 );                             // Выход из функции
       case 133 : Alert ( "Торговля запрещена." );
         return ( 0 );                             // Выход из функции
       case 134 : Alert ( "Недостаточно денег для совершения операции." );
         return ( 0 );                             // Выход из функции
       default : Alert ( "Возникла ошибка " ,Error); // Другие варианты   
         return ( 0 );                             // Выход из функции
     }
  }

물어보고 싶었다. 예를 들어 다음과 같이 129 오류에서 다음 줄을 추가할 수 있습니까?

       case 129 : Alert ( "Неправильные цены. Пробуем ещё раз.." );
         RefreshRates();                         // Обновим данные
         return ( 1 ); 
 
나는 Experts 폴더에 Visual Studio의 전체 프로젝트를 가지고 있습니다 ... 컴파일 - 이것은 .exe 파일입니까? 라이브러리 폴더에 복사하고 싶었는데... 못찾겠어요! 다음은 프로젝트 디버그 폴더입니다. 죄송합니다. 새로운 주제입니다.