mql4言語の特徴、微妙なニュアンスとテクニック - ページ 34

 
スクリプトを実行してクラッシュ(プラットフォームが閉じる)した場合、スクリプトの実行中はログファイルに記録が保存されないため、コードのエラーを検出するのがかなり難しいという問題があることに気づきました。この問題は今まで気がつかなかった。ずっとこの状態(記録が保存されていない)なのでしょうか?
 

MT4では、口座のレバレッジが変更されたかどうかを(再接続せずに)知る方法がないようです。

 
fxsaber #:

MT4では、口座のレバレッジが変更されたかどうかを(再接続せずに)知る方法がないようです。

5年前くらいにやりました。クライアントのレバレッジが特定の時間帯で減少し、変数AccountInfoInteger(ACCOUNT_LEVERAGE)で変化しなかった。そして、彼はそれを知る必要があった。

科学的なことはわかりませんが、めったに変わらない口座レバレッジと、1日に何度も変わる可能性のあるシンボルレバレッジがあると判断しています。
このように確認しました。

//+------------------------------------------------------------------------------------------------------------------+
//| Проверяет изменение плеча и сообщает если это было
//+------------------------------------------------------------------------------------------------------------------+
void leverageCheck()
{
  if(MarketInfo(Symbol(), MODE_MARGINREQUIRED) == 0) return;

   // --- получаем текущее плечо из маржинальных требований, стоимости пункта, тек.котировки
  double leverageSymb = MarketInfo(Symbol(),MODE_TICKVALUE) * Bid / MarketInfo(Symbol(),MODE_MARGINREQUIRED) / Point;
  leverageSymb = int(MathRound(leverageSymb));
  
   // --- если плечо по символу стало меньше на 10% плеча по счету отметим это
  if(leverageSymb < percVar(AccountInfoInteger(ACCOUNT_LEVERAGE), -10))
  {
    string txt = TimeToString(TimeCurrent()) + " Leverage is reduced 1:" + (string)leverageSymb;
    Print(txt, " but account leverage = " + (string)AccountInfoInteger(ACCOUNT_LEVERAGE));

    // --- вывод информации на график
  }
}

//+-------------------------------------------------------------------------------------------------------------------+
//| Получает переменную, увеличивает или уменьшает его на переданный процент и возвращает новое значение
//| Чтобы уменьшить, нужно передать percent с минусом
//+-------------------------------------------------------------------------------------------------------------------+
double percVar(double var, double percent)
{
  return var*(1 + percent/100);
}


leverageSymb シンボルで計算したレバレッジが200ではなく、199や198になることがある(レバレッジが1:200の場合)。そのため、標準的なレバレッジから一定の%を引いて、この値と比較する必要があったのです。上の解答はその時役に立ちました、便利かもしれません。

 
Vasiliy Pushkaryov #:

5年前くらいにやったんですけどね。あるクライアントが特定の時間にレバレッジを下げましたが、AccountInfoInteger(ACCOUNT_LEVERAGE) 変数には何の変化もありませんでした。そして、彼はそれを知る必要があった。

科学的なことはわかりませんが、私は、ほとんど変化しない口座レバレッジと、1日に何度も変化する可能性のあるシンボルレバレッジがあると判断しています。
このように確認しました。


leverageSymb シンボルで計算したレバレッジが200ではなく、199や198になることがある(レバレッジが1:200の場合)。そのため、標準的なレバレッジから一定の%を引いて、この値と比較する必要があったのです。そこで、上記のような解決策が役に立つかもしれません。

はい、シンボルの必要証拠金を追跡することに問題はありません。ACCOUNT_LEVERAGE - 再接続のみ。

 

チケットリストに必要な注文を記憶させ、取引履歴をフィルタリングすることは、ごく一般的なことです。そして、そのリストにあるSELECT_BY_TICKET。

チケットではなく、ポジションを記憶しているバリエーションは見たことがない。以下は、性能の比較です。

#include <MT4Orders.mqh> // https://www.mql5.com/ru/code/16006
#include <fxsaber\Benchmark\Benchmark.mqh> // https://www.mql5.com/ru/code/31279

int Filter( TICKET_TYPE &Tickets[], int &Pos[] )
{
  const int Total = OrdersHistoryTotal();            

  ArrayResize(Tickets, Total);
  ArrayResize(Pos, Total);
  
  int Amount = 0;

  for (int i = 0; i < Total; i++)
    if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) && (OrderProfit() > 0))
    {
      Tickets[Amount] = OrderTicket();
      Pos[Amount] = i;
      
      Amount++;
    }
    
  ArrayResize(Tickets, Amount);
  ArrayResize(Pos, Amount);
  
  return(Amount);
}

template <typename T>
double Func1( int TypeSelect, const T &Array[] )
{
  double Res = 0;
  const int Total = ArraySize(Array);
  
  for (int i = 0; i < Total; i++)
    if (OrderSelect(Array[i], TypeSelect, MODE_HISTORY))
      Res += OrderProfit();
      
  return(Res);
}

void OnStart()
{   
  TICKET_TYPE Tickets[];
  int Pos[];

  Print(Filter(Tickets, Pos));
  
  const double Res1 = _B(Func1(SELECT_BY_TICKET, Tickets), 1); // Так делают почти все.
  const double Res2 = _B(Func1(SELECT_BY_POS, Pos), 1);        // Не встречал.
  
  Print(Res1);
  Print(Res2);
}


2021.10.11 01:37:08.254 Test19 EURUSD.rann,M1: 561002.61
2021.10.11 01:37:08.254 Test19 EURUSD.rann,M1: 561002.61
2021.10.11 01:37:08.254 Test19 EURUSD.rann,M1: Alert: Bench_Stack = 0, 1 <= Time[Test19.mq4 49 in OnStart: Func1(SELECT_BY_POS,Pos)] = 2827 mcs.
2021.10.11 01:37:08.251 Test19 EURUSD.rann,M1: Alert: Bench_Stack = 0, 1 <= Time[Test19.mq4 48 in OnStart: Func1(SELECT_BY_TICKET,Tickets)] = 7460 mcs.
2021.10.11 01:37:08.244 Test19 EURUSD.rann,M1: 35936

チケットのバリエーションは、ほぼ3倍のパフォーマンスで負けていることがわかります。

 
fxsaber #:

チケットのバリエーションは、ほぼ3倍のパフォーマンスを失っていることがわかります。

ポジションがクローズ/オープンされた場合、チケットのロジックは壊れませんが、ポジションのロジックは壊れる可能性があります。

 
TheXpert #:

ポジションがクローズ/オープンされた場合、チケットのロジックは壊れませんが、ポジションのロジックは壊れる可能性があります。

MODE_HISTORYモードについてだけです。

 

このコードでは、関数が呼ば れる前と後に存在したいくつかの順序を見逃すことは理論的に可能でしょうか?それとも2回カウントされるのでしょうか。

double GetLots()
{
  double Lots = 0;
  
  for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS))
      Lots += OrderLots();
      
  return(Lots);
}

つまり、オーダーが削除されたり、列挙中に現れたりした場合、インデックス作成はどうなるのでしょうか?

 
fxsaber #:

または2回カウントされます。

デフォルトの時間順、チケット順を前提とすると、新しいオーダーはリストの最後に表示され、論理的には最も古いオーダーが削除されるとすべて移動することになります。

リストの先頭から順番に削除していくと、リストの1つが2回考慮されることが判明しました。 前のパスのチケットを覚えておいて比較すればよいので、回避は簡単そうです(それでも保証はありません)。

リターンパスの取得方法 - 未解明

 
Andrei Trukhanovich #:

デフォルトの時間順、チケット順を前提とすると、新しいオーダーはリストの最後に表示され、論理的には最も古いオーダーが削除されるとすべて移動することになります。

リストの先頭から順番に削除していくと、リストの1つが2回考慮されることが判明しました。 前のパスのチケットを覚えておいて比較すればよいので、回避は簡単そうです(それでも保証はありません)。

リターンパスの取得方法 - 解決していない

詳しいお返事ありがとうございましたそこで今、どうすればすべての注文を一度に処理できるかを考えています。

理由: