エラー、バグ、質問 - ページ 1931

 

朝はいつもよりいい感じ...。:)

 
Aleksey Vyazmikin:

ヘルプデスクにて

MT4です。

固定サイズのオブジェクトの場合: OBJ_BUTTON,OBJ_RECTANGLE_LABEL, OBJ_EDIT プロパティ OBJPROP_XDISTANCE と OBJPROP_YDISTANCE はチャートコーナー (OBJPROP_CORNER) に対して左上のオブジェクトポイントの位置を設定し、そこからピクセル単位の X, Y座標がカウントされることになります。


MT5です。

固定サイズのオブジェクト:OBJ_BUTTON, OBJ_RECTANGLE_LABEL, OBJ_EDIT, OBJ_CHARTでは、OBJPROP_XDISTANCEとOBJPROP_YDISTANCEプロパティは、チャートコーナー(OBJPROP_CORNER)に関連してオブジェクトの左上点の位置を設定します、そこからXとY座標はピクセルで測定されることになります。

旧バージョンのMT4では、ObjectSetを 使用して、オブジェクトをそのエッジ(コーナー)に相対的に配置できます。左側のオブジェクトでは、ピクセル計算は最初のシンボルから、右側のオブジェクトでは、最後のシンボルから行われますが、新バージョンでは、常に最初のシンボルから計算されるため、テキスト付きのラベルの配置が困難 です。開発者にお願いしたいのは、文字揃えの方法を選べるようにしてほしいということです


MT5で左右のアライメントを取る方法をご存知の方がいらっしゃいましたら、対応する関数を教えてください!

そして、怒らずにヘルプをよく読んでください。

OBJ_LABEL、OBJ_BITMAP_LABEL、OBJ_RECTANGLE_LABEL オブジェクトでは、オブジェクトのアンカー ポイントを配置するチャート角度を設定することができます。この角度は、オブジェクトプロパティOBJPROP_CORNERを介して設定され、ENUM_BASE_CORNER列挙の4つの値のうちの1つを持つことができる。

識別子

商品説明

コーナーレフトアッパー

グラフの左上隅を基準としたアンカーポイントの座標

コーナー左下

アンカーポイント座標は、グラフの左下隅を基準にしています。

コーナーライトロワー

アンカーポイント座標は、チャートの右下隅を基準として設定されます

コーナーライト・アッパー

アンカーポイントの座標は、グラフの右上隅を基準として設定されます

オブジェクトのアンカーポイントの位置はOBJPROP_ANCHORプロパティで指定され、ENUM_ANCHOR_POINT列挙の9つの値のうちの1つとすることができる。

識別子

商品説明

アンカー左上

左上隅のアンカーポイント

ANCHOR_LEFT

中央左側のアンカーポイント

アンカー左下

左下隅のアンカーポイント

ANCHOR_LOWER

中心より下のアンカーポイント

アンカー右下

右下隅のアンカーポイント

ANCHOR_RIGHT

中央右寄りのアンカーポイント

アンカーライトアッパー

右上隅のアンカーポイント

ANCHOR_UPPER

中央上部のアンカーポイント

ANCHOR_CENTER

オブジェクトのちょうど中心にアンカーポイント

 
Artyom Trishkin:

4という数字でラベル付けしようとしているリスト項目を繰り上げましょうか。ゼロになる--と、すべてが整う。

もちろん全部移動させましたよ~、私がバカなのかもしれませんが・・・。



void OnStart()
  {
      Label("0",//Название
            0,       //Окно
            10,      //X
            32,      //Y
            "0 - Центр координат в левом верхнем углу графика",
            10,//Размер шрифта
            Yellow,//Цвет шрифта
            0        //Выбор угла: 3 - нижний правый, 1 - верхний правый. 2 - нижний левый, 4 - верхний левый                   
            );     
      Label("1",//Название
            0,       //Окно
            10,      //X
            32,      //Y
            "1 - Центр координат в левом нижнем углу графика",
            10,//Размер шрифта
            Yellow,//Цвет шрифта
            1        //Выбор угла: 3 - нижний правый, 1 - верхний правый. 2 - нижний левый, 4 - верхний левый                   
            );     
      Label("2",//Название
            0,       //Окно
            10,      //X
            32,      //Y
            "2 - Центр координат в правом нижнем углу графика",
            10,//Размер шрифта
            Yellow,//Цвет шрифта
            2        //Выбор угла: 3 - нижний правый, 1 - верхний правый. 2 - нижний левый, 4 - верхний левый                   
            );
      Label("3",//Название
            0,       //Окно
            10,     //X
            32,      //Y
            "3 - Центр координат в правом верхнем углу графика",
            10,//Размер шрифта
            Yellow,//Цвет шрифта
            3      //Выбор угла: 3 - нижний правый, 1 - верхний правый. 2 - нижний левый, 4 - верхний левый                   
            ); 

  }

//+------------------------------------------------------------------+
//|Функция вывода информации на экран -- Старый вариант              |
//+------------------------------------------------------------------+
void Label(string _name,int _window,int _x,int _y,string _text,int _font,color _color,int corner)
  {
   ObjectDelete(_name);
   ObjectCreate(_name,OBJ_LABEL,_window,0,0);
   ObjectSet(_name,OBJPROP_CORNER,corner);
   ObjectSet(_name,OBJPROP_XDISTANCE,_x);
   ObjectSet(_name,OBJPROP_YDISTANCE,_y);
   ObjectSetText(_name,_text,_font,"Arial",_color);
  }
/*
//+------------------------------------------------------------------+
//|Функция вывода информации на экран -- Новый вариант               |
//+------------------------------------------------------------------+
void Label(string _name,int _window,int _x,int _y,string _text,int _font,color _color,int corner)
  {
   //corner=4;
   ObjectDelete(0,_name);
   ObjectCreate(0,_name,OBJ_LABEL,_window,0,0);
   ObjectSetInteger(0,_name,OBJPROP_CORNER,corner);
   ObjectSetInteger(0,_name,OBJPROP_XDISTANCE,_x);
   ObjectSetInteger(0,_name,OBJPROP_YDISTANCE,_y);
   ObjectSetText(_name,_text,_font,"Arial",_color);
  }
*/   
 
Artyom Trishkin:

そして、怒らないでヘルプをよく読んでください。

OBJ_LABEL、OBJ_BITMAP_LABEL、OBJ_RECTANGLE_LABEL オブジェクトでは、オブジェクトのアンカー ポイントを配置するチャート角度を設定することができます。この角度は、オブジェクトプロパティOBJPROP_CORNERを介して設定され、ENUM_BASE_CORNER列挙の4つの値のうちの1つを持つことができる。

識別子

商品説明

コーナーレフトアッパー

グラフの左上隅を基準としたアンカーポイントの座標

コーナー左下

アンカーポイント座標は、グラフの左下隅を基準にしています。

コーナーライトロワー

アンカーポイント座標は、チャートの右下隅を基準として設定されます

コーナーライト・アッパー

アンカーポイントの座標は、グラフの右上隅を基準として設定されます

オブジェクトのアンカーポイントの位置はOBJPROP_ANCHORプロパティで指定され、ENUM_ANCHOR_POINT列挙の9つの値のうちの1つとすることができる。

識別子

商品説明

アンカー左上

左上隅のアンカーポイント

ANCHOR_LEFT

中央左側のアンカーポイント

アンカー左下

左下隅のアンカーポイント

ANCHOR_LOWER

中心より下のアンカーポイント

アンカー右下

右下隅のアンカーポイント

ANCHOR_RIGHT

中央右寄りのアンカーポイント

アンカーライトアッパー

右上隅のアンカーポイント

ANCHOR_UPPER

中央上部のアンカーポイント

ANCHOR_CENTER

オブジェクトの中心を直接指すアンカーポイント

ありがとうございます。明日、何か考えてみます...。

 
prostotrader:

朝はいつもよりいい感じ...。:)

通常はそうです :)
 
SDは、この場合、正しいことだと言っています

トレーディング、自動売買システム、トレーディング戦略のテストに関するフォーラム

バグ、バグ、質問

fxsaber さん 2017.07.18 09:51

ほとんど子供じみた質問ですが、なぜそうなのでしょうか?
void OnStart()
{
  const double Norm = NormalizeDouble(8905 / 1000.0, 3);
  Print(Norm); // 8.904999999999999
  Print(DoubleToString(Norm, 3)); // 8.905
  
  const double Norm2 = (double)DoubleToString(Norm, 3);
  Print(Norm2); // 8.904999999999999
  Print(Norm == Norm2); // true
}

なぜかDoubleToStringは正規化したら意味がないと思い込んでいました。しかし、いや、台本にあるようになぜ、そのようなことになるのでしょうか。

double -> string の変換が正しく行われないようです。


この例は理解するのがややこしいので、別の例をあげました。

void OnStart()
{
  Print((double)"8.905" == 8.905); // true
  Print(((string)(double)"8.905")); // 8.904999999999999
}

こんな感じです。

Строковая в double переводится без проблем. Обратно - получаем другой результат.

例えば、"8.905 "という文字列をdoubleに変換し、すぐにstringに変換して、8.90499999999を得た。しかし、OnStartの1行目には、(double) "8.905" == 8.905と表示されています。つまり、8.905が印刷されるはずです。

もちろん、明らかなゼロエンドの状況はうまくいかないはずです。

(double) "8.9050" == 8.9050 という条件を満たせば(string)(double) "8.9050" == "8.9050" という条件も満たすはず です

この問題を少し調査したところ、次のような状況になりました。

void OnStart()
{
  const double Num = 8.274;
  const double Norm = NormalizeDouble(Num, 3);
  
  Print(Num);  // 8.273999999999999
  Print(Norm); // 8.274000000000001
}

ダブル→文字列の変換がまだ正しいとされている理由を教えてください。最後の例は、完全に私の心を揺さぶっていますね。

 
fxsaber:

ダブル→文字列の変換がまだ正しいとされている理由を教えてください。最後の例は、とても完全に心を奪われます。

最後の例へのコメント

実数は、同じ変換をすれば同一とみなすことができる。num*0.5とnum/2.0という一見同じように見える変換でも、異なる結果になる。これはミラーオペレーションについても同じことが言えます。num*=num2、num/=num2。 結果として得られる数値は、元の数値と同じにはなりません。 実数の世界へようこそ。

正規化処理では、このサンプルでは、num*=1000, num+=0.5, num/=1000の3つの実数による演算が行われた。

デバッガで手順を確認することができます

 
fxsaber:
SDは、この場合は正しいと言っています。

なぜ混乱するのでしょうか?

10進数の実数の大部分は、余りのない2進数の分数として表現することができない。その上にダブルストレージフォーマットを載せると、こんな醜いものが出来上がります。

実は、10進数型はいいんです、便利なんです。

 
Slava:

最後の例へのコメント

実数は、同じ変換を行えば同一とみなすことができる。num*0.5とnum/2.0という一見同じように見える変換でも、異なる結果になる。これはミラーオペレーションについても同じことが言えます。num*=num2、num/=num2。 結果として得られる数値は、元の数値と同じにはなりません。 実数の世界へようこそ。

この例では、正規化時に実数に対してnum*=1000, num+=0.5, num/=1000の3つの演算が行われたことになる。

デバッガで手順を確認することができます


とても建設的な説明、ありがとうございます


しかし、この反例は私の心を揺さぶります。

void OnStart()
{
  const double Num = 8.274;
  const double Norm = NormalizeDouble(Num, 3);
   
  Print(Num);  // 8.273999999999999
  Print(Norm); // 8.274000000000001
  
  Print((double)DoubleToString(Num, 3) == Num);     // true - без нормализации все замечательно
  Print((double)DoubleToString(Norm, 3) == Norm);   // false - а после нормализации полный облом!
}

正規化とはこういうものなのでしょうか?

 
Комбинатор:

なぜ混乱するのでしょうか?

Slavaの説明の後では混乱しないのですが、その後、NormalizeDouble 自体の正しさを疑わせるような例が出てきます。