どんな新人の質問でも、フォーラムを乱雑にしないように。プロフェッショナルは、通り過ぎないでください。Nowhere without you - 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));
}
//+------------------------------------------------------------------+

しかし、その仕組みはどうなっているのでしょうか。このddlをどのように参照するのかよくわからないのですが、EAのコードからですか?どうやって?まず、以下のような感じです。 #include <GetIntValue>.

2.dllを呼び出すときは、studioをオンにしておく必要はないですよね? どのように実行されるのでしょうか?

mqlのコードからこのDLLを呼び出す最も簡単な例を示してください。

 
Trader7777:

ここが分からない...。


2つ目の一方向注文が開設された場合、ロットサイズは指数関数的に(倍率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で何回か検索してみましたが、全く頭でっかちなことはなく、概ね理解できるものです。単純なことのようにさえ思えます。

しかし、その仕組みはどうなっているのでしょうか。このddlをどのように参照するのかよくわからないのですが、EAのコードからですか?どうやって?まず、以下のような感じです。 #include <GetIntValue>.

だいたいこんな感じです。これを動作させるには、dllをコンパイルしてexperts/librariesフォルダに入れる必要があります(ヘルプとチュートリアルを読んでください、そこに詳しく書かれています)。

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


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

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

2.dllを呼び出すときは、studioをオンにしておく必要はありませんよね。 では、どのように実行されるのでしょうか?

DLLは、簡単に言えば、通常のWindowsのプログラムですが、その実装している関数がユーザーからではなく、別のプログラムから呼び出されることを除けば、普通のプログラムです。これを可能にするために、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);
}
}
}
}
}
}
}


関数にパラメータを渡す必要があるため、次のようにしてください。

bool IfProfTrail=false; // 利益のあるポジションにのみ使用する - Breakevenモード
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:

ありがとうございました。

何が問題なのかが理解できました。

購入に際して、私は使用しました。

私の知る限り、買いはaskですが、iClose(Symbol(),Period(),0)はbidから価格を取得します。これがエラーの原因になっている可能性があります。

今は次のような組み合わせで使っています。

しかし、ここで疑問が生じます。このEAはPipsベースのEAではないので、価格は長い間買いゾーンにあり、ティックごとに更新されていました。

なぜトレードが始まらないのか?EAがエラーで停止し、それ以上の値動きを見ないことが判明?

Expert Advisor のテンプレートはhttps://c.mql5.com/mql4/book/mq4/experts/tradingexpert.mq4 から取得しました。

ご意見として、このEAのエラー処理機能に129と138のエラーのチェックを追加した方が良いでしょうか?

その場合、どのようにすればよいのでしょうか?

最低限、ポジションを開く/注文を設定するための独自の関数を用意し、すべてのエラーを処理する必要があります。ここで、最新の価格を知る必要があるのです。

ブランクは見ていない。しかし、私は、EAがサーバーから返されるすべてのエラーを処理する必要があると言います。そして、それはまだ十分ではありません。不測の事態が発生しても、機能を失うことなく、アルゴリズムが破綻することなく、何事もなかったかのようにポジションを回復し、作業を継続できることが必要です。

 
コンパイルして、experts/libraries フォルダに置いてください はい、どうぞ。 これからやってみます。 そして、私はそれを前に見たことがあるが、今、私は主題で、そんなに詳細かつ消化できるものを見つけることはありません。
 
artmedia70:

少なくとも、すべてのエラーを処理する、ポジションを開く/注文を設定するための独自の関数を持つ必要があります。最新の価格を知るために必要な場所です。

設計図を見たことがないんです。ただし、サーバーから返されたすべてのエラーをEAで処理する必要があることはお伝えしておきます。そして、これだけでは不十分です。不測の事態が発生しても、機能を失うことなく、アルゴリズムに不具合が発生することなく、何事もなかったかのようにポジションを回復し、作業を継続することができなければならないのです。


テンプレートは教科書から引用しています。エラー処理 関数があまり得意ではないのです。

注文開始時に、RefreshRates();があります(提案されたように、BidsとAsksをMarket Infoで置き換えています)。

 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ファイルですよね? libarriesフォルダにコピーしたかったのですが・・・。 見つからない!プロジェクトのデバッグフォルダはこちらです。 すみません、新しい話題です。