MQL5言語をゼロから独学で学ぶ - ページ 52

 

ポジションループのシンボルとウィザードによるフィルタリングに注意してください。フィルターがないのに、すべてのシンボルのすべてのオープンポジションを トロールして、これは悪いことです。

だから、一見すると何も問題ないように見える。

Совершение сделок - Торговые операции - Справка по MetaTrader 5
Совершение сделок - Торговые операции - Справка по MetaTrader 5
  • www.metatrader5.com
Торговая деятельность в платформе связана с формированием и отсылкой рыночных и отложенных ордеров для исполнения брокером, а также с управлением текущими позициями путем их модификации или закрытия. Платформа позволяет удобно просматривать торговую историю на счете, настраивать оповещения о событиях на рынке и многое другое. Открытие позиций...
 
Andrei Novichkov:

ポジションループのシンボルとウィザードによるフィルタリングに注意してください。フィルターがないのに、すべてのシンボルのすべてのオープンポジションを トロールして、これは悪いことです。

だから、一見すると何も問題ないように見えるのです。

Andreyさん、ありがとうございます!Magicについては、1つのシンボルに対して複数のポジションがオープンされることがあるので、すべて理解できましたが、別の疑問が生じました。Expert Advisor は、現在のシンボルを明示的に指定していない場合、すべてのシンボルのオープンポジションを一度に通過しますか?しかも、特定の通貨ペア、例えばEURUSDに設定されているにもかかわらず、ですか?正直なところ、この点はよく理解できません。

ウラジミールさん、ありがとうございます。

 
MrBrooklin:

アンドレイさん、どうもありがとうございます!マジックについては、1つのシンボルに複数のポジションを開くことができるので、すべて理解できましたが、もう一つ質問があります。EA は、現在のシンボルを明示的に指定していない場合、すべてのシンボルのオープンポジションを一度に調べるのでしょうか?しかも、特定の通貨ペア、例えばEURUSDに設定されているにもかかわらず、ですか?正直なところ、この点はよく理解できません。

敬具 ウラジミール


はい、すべてのシンボルのすべてのオープンポジションに設定されています。
すべての募集職種に一貫して対応。
ここで、教科書を簡単にひもといてみましょう。

https://book.mql4.com/ru/build/trading
 
MrBrooklin:

そこで、私が読んだ文献をもとに、トレーリングストップ機能付きのExpert Advisorを作成 するための短いアルゴリズムを書きました。

  1. テイクプロフィットと ストップ ロスのレベルを指定したオープンポジションの トレーリング(トラッキング)レベルの ストップ ロスの作業を自動化するExpert Advisorを作成 しましょう。
  2. Expert Advisorで、「trailing level」の設定と「trailing step」の設定の2つのパラメータを持つ入力パラメータのブロックを作成します。
  3. 新しい相場が来たら、OnTick( )関数で処理します。トレーリングは、現在のシンボルに新しいティックが来たときのみ機能します。
  4. すべてのポジションを検索するループを作成して実行してみましょう。
  5. 突然、オープンポジションが見つからなくなったら、ループに戻る
  6. 引用元をリフレッシュしています。
  7. 空いているポジションがあれば、続行します。
  8. オープンポジションの種類を定義します: 買い 、または 売り
  9. 買いポジションが ある場合、現在の価格がオープンポジションと相対的にどの位置にあるかを定義 します。
  10. 現在の価格がポジションを建てた価格より高い場合、どのレベルで上昇したかを確認します。
  11. 現在の価格が入力パラメータで定義された「トレイリングレベル 」に達した場合、ストップ ロスカット 買い ポジションの開始価格と等しいロスカットなしの レベルに移動 させます。そうでなければ、何もしない。
  12. 現在の価格がトレイリングストップレベルと同じ値だけ上回る場合 ストップ ロスは買いポジションの 開始価格レベル から トレイリングストップレベルと同じ値 だけ 移動 、価格がこのポジションに指定されたテイクプロフィットレベルに到達するまで 続きます。
  13. 価格が回転し、すでに移動した Stop Lossの レベルに達した場合、ポジションはクローズ されます。
  14. ポジションが 売り」の場合、現在の価格がオープンポジションと相対的にどの位置にあるかを定義 します。
  15. 現在の価格がオープンポジションの価格より低い場合、どのレベルで下落したかを確認します。
  16. 現在の価格が入力パラメータで指定されたトレーリング レベルに達した場合、Stop Loss 売り ポジションの開始価格と同じ損失なしの レベルに移動 させます。そうでなければ、何もしない。
  17. 現在の価格がトレイリングストップレベルと同じ値だけ上回る場合 ストップ ロスは 売り ポジションの開始レベル から トレイリングストップレベルと同じ値 だけ 移動 し、価格が そのポジションに指定された テイクプロフィットレベルに到達するまで続きます。
  18. 価格が反転し、 Stop Lossの レベルに達した場合、ポジションはクローズ されます。

アルゴリズムを見直し、どのような点が見落とされているのか、ヒントを教えてください。

敬具 ウラジミール

理論は悪くないので、次は実践に力を入れましょう。うまくいくのか?

 
Aliaksandr Hryshyn:

理論は悪くないが、次は実践だ。できるのか?

やってみます。しかし、これにはまったく別のレベルの知識が必要で、私にはまだそれがないことを理解しているはずです。

ウラジミールさん、ありがとうございます。

 
Aleksey Masterov:

はい、すべてのシンボルのオープンポーズで...
すべてのオープンポーズで一貫して
ここでは、すでに教科書に載っている簡単なトローリングを紹介します。

https://book.mql4.com/ru/build/trading

はい、Alexey、私はこのコードをすでに見ました。インクルードファイルの形になっています。正直なところ、何度か閲覧していますが、その中にシンボルに関するものは見当たりません。もしかしたら、私が何かを勘違いしているか、検索が下手なだけかもしれません。

敬具 ウラジミール

 

とりあえず、機能の説明を続けましょう。

先ほども書きましたが、関数はどこにでもあるもので、それを愛し、その書き方を知らなければならないのです。機能とは、地球規模の問題を解決するための小さな戦士なのです。もし私たちが軍隊の将軍だとしたら、どんな戦闘員をコントロールしたいですか?大まかなリストはこんな感じです。

  • ファイターは命令を明確に実行しなければならない。歩兵の平均的な知能レベルは、決して高くはありません。したがって、このような戦闘機には、「バンカーを奪う」、「舌を取る」、「橋を採掘する」など、明確でシンプルな目標を設定するのがよいでしょう。
  • もし課題が困難であれば、それを達成するための超賢い戦闘機を探す必要はない。タスクをいくつかのサブタスクに分割して、2つか3つのより愚かな、しかしより効率的な戦闘機を取る方が良い。全員が何の疑問も持たずにサブタスクを解決する、あるいは、コンセプトやタスク全体について無知であるようにするのがよいでしょう。そうすれば、誰かが捕虜になっても問題ないし、計画の全貌が明らかになることもない。
  • 雪が降ろうが、雨が降ろうが、パリにいようが、女がいようが、兵士は命令に従わなければならない。もし、そうした周囲の環境が命令の遂行に影響を及ぼさないのなら、そうした条件や外部環境は無視されなければならないのだ。
  • タスクが難しいということもあります。それを解決するために多くの戦闘機が必要なのです。各ファイターにジェネラルを割り当てることはできません。その代わり、頭のいい兵士を配置して、複数の戦闘員を統率する必要があります。この一団は、今度は同じように兵隊の中隊で結束し、上官を任命する。

しかし、話が脱線してしまったので、再び機能の話に移ろう。

ある関数が一般的な問題を解決しすぎる場合、例えるなら、その関数で何か問題が起きれば、企業全体が台無しになりかねない非常に賢い戦闘員ということです。このような関数が何をするのかと問われれば、答えは長くなる可能性がある。この関数の結果が突然正しくなくなった場合、そのエラーの原因を突き止めるのは非常に困難です(多くのタスク、多くのコード、多くのサブプロシジャの呼び出しがあり、どこで正確にエラーが発生したのかが分かりにくいため)。

ある関数が、月、水、日、そして「気分」によって休みの日に正しい結果を計算 するとしたら、この関数に頼っていいのだろうか?例えばOrderSend関数が木曜日だけポジションをオープンし、何らかのマジックパラメータ13が定義されている場合を想像してください。そして、これはナンセンスでもファンタジーでもまったくない。この動作は、外部環境のパラメータに関数を依存させるだけで、指一本でアレンジすることができます。

関数があるとする。

double sum(double a, double b)
{
   return a+b;
}

は、外部環境に関係なく、常に2つの値の和を返します。つまり、この関数を他のスクリプトやExpert Advisorにコピーしても、全く問題なく動作するのです。この関数は一度書いておけば、あとはオブラートに包んでコピーするだけで、多くのプログラムで利用することができます。その結果、私たちは、その動作が何にも依存していないことを知り、常にその結果を信頼することができるようになります。このような、環境に依存しない関数は、副作用のない 関数、あるいは純粋関数と 呼ばれます。純粋な関数を書こうと努力すると、すぐにたくさんの関数が出来てしまう。つまり、ファイルにまとめて、新しいプロジェクトに含めることができるのです。これを コードの再利用と いいます。二度手間はしない。その代わり、私たちが知っている、信頼性が何度も検証された、すでに書かれた関数を使います。

では、次に反例をみてみましょう。

double c = 0.0;
double sum(double a, double b)
{
   return a+b+c;
}

cは 常に0であるため、結果は同じと思われる。それとも、いつもではないのでしょうか?どこかで誰かがCを 変更したら?では、どうするのか?もし、どこかの誰かが、自分自身の目的のために、外部変数cも使っていて、その人が別の型、たとえば文字列の変数cを持っていたらどうでしょうか?この2つの関数を組み合わせることは、もはや不可能です(コンパイラは、同じ名前の2つの変数を宣言することを許可しません)。また、その共通の依存関係も解決するのが難しい。まったくもって、どうしたらいいのかわからない。例えば、これらの機能を連携させる確実で簡単な方法を私はまだ知らないのです。

他に関数がなく、一つの関数だけが外部変数を読み取る場合でも、それを別の場所にコピーするのはそう簡単ではない。この関数とその依存 関係の両方をコピーする必要があります。しかし、これらの関数を共通のファイルにコピーしたらどうでしょう。そこでは、このような機能が50も100もあるんです。そして、それぞれが自分自身の従属変数を山ほどコピーしている。関数の不明確な関連変数が絡んでくるのです。しかし、それは何のためなのか?どんな問題を解決するのか?ほとんどの場合、不要な依存関係を作らずに済むのに、なぜ不要な依存関係を作るのでしょうか?

関数には、もう一つ驚くべき特徴があります。機能は自明である。つまり、図式を描かなくても、いい名前を選んで、一般的なアルゴリズムを関数に分割すればいいのです。以下はその一例です。

void OnTick()
{
   if(SelectFirstPendingOrder(ORDER_TYPE_BUY))
       CancelSelectPendingOrder();
}

関数も書かれていないので、このコードが何をするものなのかわかりません。しかし、私が読むとしたら、方向が ORDER_TYPE_BUY の <最初の> 保留注文がうまく選択されたら、それがキャンセルされる(最初の関数が選択し、2番目の関数がキャンセルする)ということだろう。このコードは1ティックごとに実行されるので、いくら保留中の注文があっても、遅かれ早かれそれぞれがキャンセルされることになる。また、買い注文を出そうとすると、その注文は即座に取り消されます。同時に、売り注文も問題なく出すことができる。

2行のコードと2つの関数だけです。そして、そのアルゴリズムは自明でなく、さらに重要なことは、信頼性が高いということです。

MCLを語るとき、純粋関数についてもう少し触れておく必要がある。ア プリケーション言語であるため、端末が提供するデータに頼らなければ何も書けないのが難点だ。結局のところ、これが主な仕事なのです。取引環境と適切に対話することです。形式的には、価格、注文数、残高の変化など、あらゆる取引環境は変化しやすいものです。したがって、このような変化しやすい取引環境と相互作用する機能は不明である。なぜなら、外部の取引環境は、常に変化している何らかのグローバルな変数と考えることができるからです。しかし、OrdersTotal()を書いたとき、この関数が常に同じ値を返すとは思っていません。その代わり、当然ながら変動する保留注文の数を返してくれることを期待しています。したがって、MQLでは、OrdersTotal()のように外部APIの関数を呼び出す場合でも、クリーンで再利用可能な関数と見なすことにしています。それは、私たちの合理的な甘えでしょう。

 
Vasiliy Sokolov:

続いて、機能について...。

Vasilyさん、私だけではなく、このトピックを読んでいる、または読もうとしている初心者プログラマーにも 貴重な知識を教えてくれて、本当にありがとうございます。

ウラジミール、同じ大きな敬意をもって。

 

プログラミング言語「MQL5」の勉強を続けています。Trailing_Stop Expert Advisorのコード作成アルゴリズムについて重大な指摘はなかったが(シンボルとマジックについては覚えているので、後でアルゴリズムに追加します!)、EA用の入力パラメータを作成し、オープンポジションの検索を開始するループのコードを書いた。

Expert Advisor を実行すると、問題が発生しました。取引ターミナルの「Experts」タブに、通貨ペア EURUSD のチャートが1 つしかなく、ポジションも 1 つ しか開いていないのに、「A loop has started」という同じメッセージが 毎ティックに表示されます。そして、これらのメッセージは、出力される時間が全く同じなのです。

夜中まで戦いましたが、勝てませんでした。何が問題なのか理解できない。


Expert Advisor のコードは英語で書かれており、コメントをロシア語にすることで、より簡単に処理できるようにしています。このEAでは、先ほどお約束したように、プログラミングスクールの中学1年生にもわかるように、すべてを説明することを心がけました。

ウラジミールさん、ありがとうございます。

//+------------------------------------------------------------------+
//|                                                Trailing_Stop.mq5 |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"

input ushort TrailingLevel=100; //Уровень трейлинга (для включения)
input ushort TrailingStep=10;   //Шаг трейлинга (для перемещения)
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   /* Для цикла for создаем локальную переменную i и присваиваем ей значение "торговая функция PositionsTotal",
      которая возвращает нам количество открытых позиций*/
   int i=PositionsTotal();
   /* Разберемся, что такое оператор for.
      Оператор for состоит из трех Выражений и выполняемого Оператора:
      for(Выражение_1; Выражение_2; Выражение_3)
         Оператор;
      Выражение_1 описывает инициализацию цикла. За инициализацию цикла будет отвечать "Торговая функция PositionsTotal".
      Выражение_2 проверяет условия завершения цикла. Если оно истинно, то выполняется Оператор в теле цикла for.
      Все повторяется до тех пор, пока Выражение_2 не станет ложным. Если оно ложно, цикл заканчивается
      и управление передается следующему оператору.
      Выражение_З вычисляется после каждой итерации (т.е. после каждого повторения действия).
   */
   for(i; i>=0; i--) //запускаем цикл перебора открытых позиций (i) от максимума до нуля (i>=0) с шагом минус 1 (i--)
      Print("Запущен цикл");
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---

  }
//+------------------------------------------------------------------+
 
MrBrooklin:


iはオープンポジションの 数に等しいので、多くのサイクルが印刷となります。

Print("Запущен цикл");
の"="記号を削除する必要があります。
   for(i; i>=0; i--)
オープンポジションの数が0のときに、なぜループを通過する必要があるのでしょうか。この0の呼び出しが、2つ目の印刷が行われる場所です。