どんな新人の質問でも、フォーラムを乱雑にしないように。プロフェッショナルは、通り過ぎないでください。Nowhere without you - 6. - ページ 641

 
simpleton:

なぜエラーをエミュレートするのか?

エラー - システムの制限や障害に関連する何らかの理由で、アルゴリズムを実行できず、何らかの(もちろん限定的ではあるが)保証のある結果を得ることができなかったことを知らせるものである。FillAndPrint()関数は、ちょうどエラーの状況が何を意味し、何を意味しないかを雄弁に物語る。エラーが発生した場合は、結果を印刷しようともしない。エラーがなければ、その結果は信頼できる。このように、エラー/ノーエラーのロジックを構築する必要があります。

ここで、アルゴリズムを変更する必要があります:追加のフィルターを適用する必要があります。

こうあるべきなのです。

まず、オブジェクトの種類とパラメータで「フィルタリング」を行い、利用可能なすべてのオブジェクトの中から必要なものだけを選択し、さらにフィルタをかける。大体、人がやるような感じです。それが人というものでしょう?

このような小さなサブタスクには、それぞれ別の機能を持たせることが望ましい。

例えば、2倍する必要があり、それがアルゴリズムの本質である場合など、非常に特殊な場合を除き、式の中に数字を入れてはいけません。そうすると、数字の2がそのまま式の中で使えるようになります。その他にも、そのような非常に稀なケースもあります。

その他の場合は、ニーモニックを使用する必要があります。まず、現地の状況を把握しやすくなるため、失敗が少なくなります。そして第二に、値そのものが一箇所で定義されているので、必要に応じて変更することが容易であり、アルゴリズムで複数回数字を使う場合や、ニーモニックを使わずにアルゴリズムの何箇所かで数字を固定しなければならない場合に比べ、間違いがないであろうということである。

実行の結果

オブジェクトは一つも見つかりません。両方のニーモニックの値を10回ずつ増やして36000(10時間)にし、再度実行します。

一つのトレンドは、すでにフィルタリングを「通過」している。では、最初のニーモニックの値を3600に戻して実行してみましょう。

どちらの傾向も、現在ではフィルタリングを「通過」していることがわかる。ちなみに、このようなプログラムのデバッグは、どれかひとつのブランチではなく、すべてのブランチ(部分)をデバッグすることをお勧めします。

なんとなく形式的に説明するために、このように説明してみます。プログラムは、どうやら計画のようです。

各主要計画項目は、より小さな副計画項目に分解することができます。小さいものをさらに小さいものへ。最小のサブプランの項目は直接実行される。

各プラン、サブプラン、さらに小さなサブプランは、プログラム内の機能に対応しています。最小のサブプランの項目は、システム関数だけを呼び出す、あるいは呼び出さない「エンド」関数に相当し、例えば、AddValue()やDiffInSecs()は、前述したものの例である。上のサブプランの項目は、下のサブプランの項目を実装する関数を呼び出す関数に対応しています。上述したものでは、MassTrendNumber()、AddValueIfFound()、AddValueIfFiltered()がこれにあたります。また、「低レベル」の関数は「高レベル」の関数を呼び出してはならず、「高レベル」の関数は基本的に数レベル下にジャンプしてはならない、つまり、基本的に下のレベルの関数を呼び出すだけであるべきである。このルールは、"低レベル "の方が "高レベル "よりもはるかに厳しい。

このようなツリー構造で結ばれた(短い)関数として、誰が誰を呼ぶかという感覚で、プログラム中のアクションを整理して作ってみてください。

このプログラムは、1本の枝が何度も「枝分かれ」する「縮退木」になっています。そして、それは2つの小さな枝ではなく、1つの枝に「分岐」します。しかし、「高水準」の機能が「低水準」の機能を一貫して呼び出している点は、見て取れる。今回の修正では、この構造にもう1レベル、「非分岐分岐」であるAddValueIfFiltered()を挿入しています。

出来上がったコードを貼り付けます。

課題:トレンドライン(OBJ_TREND)を検索し、現在のバーからの相対的な価格値を配列に記録することです。オブジェクトの時間パラメータ(OBJ_TREND)の存在に対してフィルタリングされる。

#property strict

/******************************************************************************/
bool AddValue(double &array[], const double value) {
  const int size = ArraySize(array);

  if (ArrayResize(array, size + 1) != size + 1) {
    return false; // Ошибка, значение не может быть добавлено к массиву
  }

  array[size] = value; //записываем
  return true; // Нет ошибки, значение добавлено к массиву
}

/******************************************************************************/
bool AddValueIfFound(double &array[], const string name) {
  const int type = ObjectType(name);

  if (type == OBJ_TREND) {
    switch ((color)ObjectGet(name, OBJPROP_COLOR)) { // Тип color допустимо использовать в switch
    case Goldenrod:
    case Gainsboro:
    case White:
      if (!AddValueIfFiltered(array, name)) { // Пропускаем через фильтр
        return false;
      }
    }
  }

  return true; // Нет ошибки, значение, если найдено, добавлено к массиву
}
/******************************************************************************/
bool MassTrendNumber(double &array[], const bool buy) { // Поиск значения цены трендовой линии, текущего бара, запись в массив. Два массива: masS и masB
  const string subname = (buy ? "uptrendline" : "downtrendline"); // существует два названия трендовых линий, первое и второе

  if (ArrayResize(array, 0) != 0) {
    return false; // Ошибка, массив не может быть заполнен достоверно
  }

  for (int i = 0, limit = ObjectsTotal(OBJ_TREND); i < limit+2; i++) {
    if (!AddValueIfFound(array, subname + IntegerToString(i))) {
      return false; // Ошибка, массив, если и заполнен, то недостоверно
    }
  }
 
  return true; // Нет ошибки, массив заполнен достоверно
}
/******************************************************************************/
long DiffInSecs(const datetime dt1, const datetime dt2) {
  return dt1 - dt2;
}
/******************************************************************************/
bool AddValueIfFiltered(double &array[], const string name) {
#define MIN_SECS_BETWEEN_PRICE1_AND_PRICE2 3600
#define MAX_SECS_AFTER_PRICE2              3600

  const datetime dt1 = (datetime)ObjectGet(name, OBJPROP_TIME1);
  const datetime dt2 = (datetime)ObjectGet(name, OBJPROP_TIME2);
  const datetime dt = TimeCurrent();
  
  Print("name = ", name,// ", dt = ", dt, ", dt1 = ", dt1,"\n", 
  " DiffInSecs = ", DiffInSecs(dt,dt2)," DiffInSecs = ", DiffInSecs(dt2,dt1));

   if( DiffInSecs(dt,dt2)>MAX_SECS_AFTER_PRICE2 && DiffInSecs(dt2,dt1)> MIN_SECS_BETWEEN_PRICE1_AND_PRICE2){
    if (!AddValue(array, ObjectGetValueByShift(name, 1))) { // Пытаемся добавить
      return false; // Ошибка, значение не добавлено
    }
  }

  return true; // Нет ошибки, значение, если удовлетворило условию фильтра, добавлено к массиву
}

/******************************************************************************/
void FillAndPrint(double &array[], const bool buy) {
  if (MassTrendNumber(array, buy)) {
    const int limit = ArraySize(array);

    Print("Найдено объектов: ", limit);

    for (int i = 0; i < limit; i++) {
      Print("Price[", i, "] = ", DoubleToStr(array[i], Digits));
    }
  } else {
    Print("Чёрт!");
  }
}

/******************************************************************************/
void OnTick()

//=============================================================================================
//====================================== Линии тренда =========================================
//=============================================================================================
 double masS[]; double masB[];

  Print("Sell:");
  FillAndPrint(masS, false);

  Print("Buy:");
  FillAndPrint(masB, true);
 simpletonСпасибо вам большое, вы за пестовали меня на ощущения правильного кода!) (Правда я немногое понял))))
 
evillive:

私は今4桁の数字を持っていますが、ewardollarでは1ロットで1ポイントが10ドルで、ずっとそうでした。クロスの場合、コストは8から16になり、計算式はもう少し複雑になります。

例えば、ユーロポンドの場合、marketinfoは16.984を返し、ポンドドルの為替レートは1.6984、つまりユーロポンドの1ピップは1ポンドの価値があり、ポンドドルのポイント値は常に10.0(100000 * 0.0001 = 10.0 または 100000 * 0.00010 = 10.0 - 好きな方を選択)であり、これに乗じています。


これらの計算はすべて、あなたの口座がドル建てである場合にのみ正しく行われます。

この場合、xUSD(EURUSD、GBPUSDなど)の場合、tickvalue = lot*point = 100000*0.0001 = 10.0となります。

USDh(USDCHF、USDJPYなど)の場合 tickvalue = lot*point/Bid = 100000*0.01/101.93=9.8107

xUSD/yUSD(EURGBP)の場合 tickvalue = Bid(yUSD)*lot*point = 1.6980*100000*0.0001 = 16.98となります。

xUSD/USDy (EURJPY)の場合 tickvalue = lot*point/Bid(USDy) = 100000*0.01/101.91 = 9.8126


何か失敗したのか!?時間をかけてコードを調べ、表現を選択し、見る。

  double TV = MarketInfo(Symbol(),MODE_TICKVALUE); 
  string sTV = DoubleToStr(TV,4); 
  Comment("TV ",sTV); //sTV = 1.0/Bid

これ以上ないほどシンプルです。10、16などなし。

 
evillive:

私は今4桁の数字を持っていますが、ewardollarでは1ロットで1ポイントが10ドルで、ずっとそうでした。クロスの場合、コストは8から16になり、計算式はもう少し複雑になります。

例えば、ユーロポンドの場合、marketinfoは16.984を返し、ポンドドルの為替レートは1.6984、つまりユーロポンドの1ピップは1ポンドの価値があり、ポンドドルのポイント値は常に10.0(100000 * 0.0001 = 10.0 または 100000 * 0.00010 = 10.0 - 好きな方を選択)であることを掛け合わせています。


これらの計算はすべて、あなたの口座がドル建てである場合にのみ正しく行われます。

この場合、xUSD(EURUSD、GBPUSDなど)の場合、tickvalue = lot*point = 100000*0.0001 = 10.0となります。

USDx(USDCHF、USDJPYなど)の場合 tickvalue = lot*point/Bid = 100000*0.01/101.93 = 9.8107

xUSD/yUSD(EURGBP)の場合 tickvalue = Bid(yUSD)*lot*point = 1.6980*100000*0.0001 = 16.98となります。

xUSD/USDy (EURJPY) クロスの場合 tickvalue = lot*point/Bid(USDy) = 100000*0.01/101.91=9.8126




こんなの間違ってる!見積もり額は関係ない! そして、min.tickの値は現在の価格から 計算されなければならない!TICK_VALUEに等しい!上記は、私のコードの例です。
 
borilunad:

borilunad:

こんなの間違ってる!見積書の価値は関係ない! また、min.tickの値は、現在の価格から計算されるべきですTICK_VALUEに等しい!上記は、私のコードの例 です。

どう間違っているのでしょうか?Marketinfoは、上にあげた計算式と同じ値を返します。これらの数式は私が考案したものではなく、端末がTickValueを計算するために使用しているものです)))

Marketinfoから値を取った方が便利なのは確かだが、計算式や計算方法を教えてほしいということだった。

そして、先ほど書いた値については、5桁の カウントでは1ポイント=10ピップスであり、4桁のカウントでも同じポイントなので、問題ないとのことです。

 
evillive:

どう間違っているのでしょうか?Marketinfoは、上にあげた計算式と同じ値を返します。これらの数式は私が考案したものではなく、端末がTickValueを計算するために使用しているものです)))

Marketinfoから値を取った方が便利なのは確かだが、計算式や計算方法を教えてほしいということだった。

そして、先ほどシグニチュードについて、5桁のカウントでは1ポイント=10ピップスだから関係ないと書きましたが、これは4桁のときと同じポイントなんです。


MarketInfo(Symbol(),MODE_TICKVALUE) =1.0/Bid;多分ユーロドルだけで、他には噴射しない!という のは、そういうことです。
 
borilunad:

MarketInfo(Symbol(),MODE_TICKVALUE) =1.0/Bid;多分、ユーロだけで、他は ダメ!というのはそういうことです。

これはまさにユーロドルの問題点であり、ヘルプに記載されている定義に基づけば

MODE_TICKVALUE

16

預け入れ通貨での証券価格の変動が少ない こと


そして、増殖させるという意味

MODE_POINT

11

引用通貨におけるポイントの大きさ。現在のシンボルは、定義済み変数Pointに格納されます。



MODE_LOTSIZE

15

商品の基準通貨での契約サイズ


もちろん、あなたの口座がユーロ建てであれば、ユーロを基本通貨として使用すべきですが、ドル建て口座を持つトレーダー(ほとんどの場合そうです)には、上記の計算式が有効 です。主要かつ最も取引されているペアは米ドルをベースにしているため、これらの計算式が最もよく使用されます。

 
evillive:

これは、ヘルプに記載されている定義に基づくと、まさに間違いです。

MODE_TICKVALUE

16

預け入れ通貨でのシンボル価格の最小限の変更


この値に乗算する必要があるということです。

MODE_POINT

11

引用通貨におけるポイントの大きさ。現在のシンボルは、定義済み変数Pointに格納されます。



MODE_LOTSIZE

15

商品基準通貨での契約サイズ


もちろん、ユーロ建ての口座であればユーロを使うべきですが、ほとんどのトレーダーはドル建ての口座を持っています。


では、特殊なケースですが、ユーロ圏に住む私にとっては、すべての計算をユーロで行った方が便利なんですねー。
 

皆さん、以下のインジケーターのコード例を教えてください。バッファーはいくつ必要で、どのようなマッピングで、どこに、どのようなプロパティを規定すればいいのかがわからない。

指標は以下の通りです。

1 バーは、少なくとも3本目と隣接するバーごとに接続されています。ラインは赤色です。

2 バーセクションは、5本目と隣接するバーごとに最大値を接続します。線は青色です。

要は、セグメントが一切交差していないことです。それぞれのセグメントの開始と終了は、他のセグメントから独立しています。

インジケータは、各区分の開始と終了の値を計算する。条件によって色を変える必要があります。

だいたいこんな感じです。


 

そしてもう一つの質問。

デバッグモードで インジケータを操作できないのは正常ですか?

プログラムが停止点に達すると、MT4ターミナルがハングアップし、ウィンドウが白色(HP内)になり、チャートに描かれているものが見えなくなります

 
Top2n:

以下、準備中のコードです。

タスク:トレンドライン(OBJ_TREND)を検索し、現在のバーからの相対的な価格値を配列に記録します。オブジェクトタイムパラメータ(OBJ_TREND)の有無に関するフィルタリングあり。

simpleton:ありがとう ございます正しいコードを感じさせていただきました!) (あまり理解できませんでしたが))))

練習すれば、どんどん理解できるようになる。集中力と気配りが必要です。プログラムアルゴリズムが1つの大きな機能にまみれていると、集中力や注意力を持って実現することが難しく、リンクが多くなりすぎてしまうのです。しかし、プログラムが機能的に完全な部分(小関数)に分割されていれば、個別の小関数ごとに行う方がはるかに簡単である。そして、各機能レベルでもそうです。ちなみに。

   if( DiffInSecs(dt,dt2)>MAX_SECS_AFTER_PRICE2 && DiffInSecs(dt2,dt1)> MIN_SECS_BETWEEN_PRICE1_AND_PRICE2){
    if (!AddValue(array, ObjectGetValueByShift(name, 1))) { // Пытаемся добавить
      return false; // Ошибка, значение не добавлено
    }
  }
MAX_SECS_AFTER_PRICE2というニモニックの名前を間違えたのでしょう(最初は条件が逆でなければならないとそう理解していたので)、意味はおそらくMIN_SECS_AFTER_PRICE2、つまり最大ではなく、許容最小であるべきなのです。