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

 

ilunga:

追伸:私の(そしてあなたの)コードでは、bar_info[1]は現在のバーの最大値であると仮定してよいでしょうか?

誰も現在のバーについて何も言っていない。:)

この例では、現在のバーを正確に表示する必要があります。

1. 配列の方向を定義する(0 bar - 現在または最高値)。

今回のように、配列を移動させる場合は、初期化ブロックの中で一度だけ行えばよいでしょう。関数の中で配列を隠すと、その場で定義してしまうのです。

2.配列がシリーズとして宣言されている場合、現在のバーは0となり、その前に閉じたバーは1となります。

少なくとも、私の記憶では。

 

何か見落としているかもしれませんが、現在のバーで開くには(すべての追加を考慮して)次のようになります。

配列を関数に移動させる!

//Function BUY_pending
bool BUY_pending(string symbol,ENUM_TIMEFRAMES period,double volume,ulong magic = 0)
{
//----------------------------------------------------------------------------//
//Work variables
double price = 0, sl = 0, tp = 0; //Prices: Open, Sell stop, Take profit
int ResCopy = -1; //Result of copying the data into an array
int Dig     = 0;  //Digits

double bar_info[1];

bool Result = true; //Returned importance
//----------------------------------------------------------------------------//

ResetLastError();

//Checking the signal to stopping the trading system
  if(IsStopped()) return(false);
//Preparation of array
ArraySetAsSeries(bar_info,true);
//Preparation of structures
ZeroMemory(TradeRequest);
ZeroMemory(TradeResult);
ZeroMemory(CheckResult);
//Copying the data into an array
ResCopy = CopyHigh(symbol,period,0,1,bar_info);

  if(ResCopy==-1)return(false); 
//Calculations
Dig   = (int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);

price = NormalizeDouble(bar_info[0] + 500*_Point,Dig);
sl    = NormalizeDouble(price - 200*_Point,Dig);
tp    = NormalizeDouble(price + 1000*_Point,Dig);
//Preparation of request
TradeRequest.type_filling = ORDER_FILLING_FOK;
TradeRequest.action       = TRADE_ACTION_PENDING;
TradeRequest.type         = ORDER_TYPE_BUY_STOP; 
TradeRequest.deviation    = 10;
TradeRequest.symbol = symbol;
TradeRequest.magic  = magic;
TradeRequest.volume = volume;
TradeRequest.price  = price;
TradeRequest.sl     = sl;
TradeRequest.tp     = tp;
//Checking
Result = OrderCheck(TradeRequest,CheckResult);

  if(!Result)
  //Print message for user
  {
  PrintFormat("retcode=%d",CheckResult.retcode);

  PrintFormat("%s %s at %G Ask=%G  Bid=%G  ",
              EnumToString(TradeRequest.type),symbol,TradeRequest.price,SymbolInfoDouble(symbol,SYMBOL_ASK),
              SymbolInfoDouble(symbol,SYMBOL_BID));                  
  Print("------------");
  }

  if((!Result)||(CheckResult.retcode!=0))return(false);
//OrderSend
Result = OrderSend(TradeRequest,TradeResult);
//Checking for presence of the errors
  if(_LastError!=0){Result = false;}
//----------------------------------------------------------------------------//
return(Result);
//----------------------------------------------------------------------------//
}
 
Interesting:

そして、誰も現在のものについては何も言っていない。:)

例題を作り直しただけです。 現在のものが必要な場合は、そうしなければなりません。

1.アレイシリーズの方向を定義する(0 bar - 現在または最新)。

今回のように、配列を移動させる場合は、初期化ブロックの中で一度だけ行えばよいでしょう。関数の中で配列を隠すと、その場で定義してしまうのです。

2.配列がシリーズとして宣言されている場合、現在のバーが0となり、その前に閉じたバーが1となります。

少なくとも、私の記憶では。

配列を3要素に拡張してみました。現在の価格と 中身がミスマッチしてしまったんです。これが一番の理由だと思います。

#include <Trade\SymbolInfo.mqh>
double bar_info[3];

CSymbolInfo m_sym1;
CSymbolInfo m_sym2;

bool a;
int OnInit()
{
   SymbolSelect("EURUSD",true);
   SymbolSelect("GBPUSD",true);
   a = false;   
   return(0);
}

void OnTick()
{
   if (a) return;
   a = true;
   int ResCopy = CopyHigh("EURUSD",PERIOD_D1,0,3,bar_info);
   if(ResCopy==-1)return;
   Print("bar_info[0] = " + DoubleToString(bar_info[0]));
   Print("bar_info[1] = " + DoubleToString(bar_info[1]));
   Print("bar_info[2] = " + DoubleToString(bar_info[2]));
   PrintFormat("Ask=%G  Bid=%G  ", SymbolInfoDouble("EURUSD",SYMBOL_ASK), SymbolInfoDouble("EURUSD",SYMBOL_BID));
}

結果(テストはGBPUSDで行いました。)

FR      0       test3 (GBPUSD,H1)       13:12:59        2012.01.02 09:00:00   bar_info[0] = 1.29591000
LH      0       test3 (GBPUSD,H1)       13:12:59        2012.01.02 09:00:00   bar_info[1] = 1.29987000
OF      0       test3 (GBPUSD,H1)       13:12:59        2012.01.02 09:00:00   bar_info[2] = 1.29220000
QN      0       test3 (GBPUSD,H1)       13:12:59        2012.01.02 09:00:00   Ask=1.29722  Bid=1.29709  

AskとBidの両方がゼロの最大値より大きく、2本目のバーの最大値より大きいことがわかる


EURUSDでテストを実行すると、すべてOKです。

FL      0       test3 (EURUSD,H1)       13:21:09        2012.01.02 09:00:00   bar_info[0] = 1.29591000
LJ      0       test3 (EURUSD,H1)       13:21:09        2012.01.02 09:00:00   bar_info[1] = 1.29987000
OP      0       test3 (EURUSD,H1)       13:21:09        2012.01.02 09:00:00   bar_info[2] = 1.29220000
CO      0       test3 (EURUSD,H1)       13:21:09        2012.01.02 09:00:00   Ask=1.29241  Bid=1.2922  


not my」ペアのテストでは、「バーの情報は更新されたが、ティックはまだ存在しない」という状況になるような気がします。

 
ilunga:

配列を3要素に拡張しました。現在の価格と 配列の内容に矛盾があるのですが。それが一番の理由でしょう。

結果

AskとBidがともに0本目の棒グラフの最大値より大きく、2本目の棒グラフの最大値より大きいことがわかる。

配列の直列性を考慮しないコードですね。この結果で、例えば2000年に0バールがないとは誰も保証できない。

上記のコードは、配列 variant に含まれるすべての TF に適しています。

このコードがあるのは、理由があるのです。

//Preparation of array
ArraySetAsSeries(bar_info,true);

もし、日足タイムフレーム(D1)だけでバーの最大値を特定したい場合は、配列を処理する必要はなく、関数の最初の部分を次のように変更するだけです。

//Function BUY_pending
bool BUY_pending(string symbol,double volume,ulong magic = 0)
{
//----------------------------------------------------------------------------//
//Work variables
double price = 0, sl = 0, tp = 0; //Prices: Open, Sell stop, Take profit
double High  = 0; //The maximum value of bid for the current day

int Dig     = 0; //Digits

bool Result = true; //Returned importance
//----------------------------------------------------------------------------//

ResetLastError();

//Checking the signal to stopping the trading system
  if(IsStopped()) return(false);
//Preparation of structures
ZeroMemory(TradeRequest);
ZeroMemory(TradeResult);
ZeroMemory(CheckResult);
//Calculations
High = SymbolInfoDouble(symbol,SYMBOL_BIDHIGH);
Dig  = (int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);

price = NormalizeDouble(High + 500*_Point,Dig);
sl    = NormalizeDouble(price - 200*_Point,Dig);
tp    = NormalizeDouble(price + 1000*_Point,Dig);
 
Interesting:

配列の直列性を考慮したコードになっていませんね。この結果で、0バールが2000年にならないとは誰も保証できない。

上記のコードは、配列 variant に含まれるすべての TF に適しています。

このコードには理由があります

ArraySetAsSeriesは動的配列のみ
Документация по MQL5: Основы языка / Типы данных / Объект динамического массива
Документация по MQL5: Основы языка / Типы данных / Объект динамического массива
  • www.mql5.com
Основы языка / Типы данных / Объект динамического массива - Документация по MQL5
 
Interesting:

配列の直列性を考慮したコードになっていませんね。この結果、0バールが2000年にならないとは誰も言い切れない。

上記のコードは、配列 variant に含まれるすべての TF に適しています。

このコードがあるのは、理由があるのです。

よし、配列をダイナミックにしよう。

#include <Trade\SymbolInfo.mqh>
double bar_info[];

CSymbolInfo m_sym1;
CSymbolInfo m_sym2;

bool a;
int OnInit()
{
   ArrayResize(bar_info, 3);
   ArraySetAsSeries(bar_info,ххх);
   SymbolSelect("EURUSD",true);
   SymbolSelect("GBPUSD",true);
   a = false;   
   return(0);
}

void OnTick()
{
   if (a) return;
   a = true;
   int ResCopy = CopyHigh("EURUSD",PERIOD_D1,0,3,bar_info);
   if(ResCopy==-1)return;
   Print("bar_info[0] = " + DoubleToString(bar_info[0]));
   Print("bar_info[1] = " + DoubleToString(bar_info[1]));
   Print("bar_info[2] = " + DoubleToString(bar_info[2]));
   PrintFormat("Ask=%G  Bid=%G  ", SymbolInfoDouble("EURUSD",SYMBOL_ASK), SymbolInfoDouble("EURUSD",SYMBOL_BID));
}

xxxの代わりにtrueとfalseを入れました。

その結果

FF      0       test3 (GBPUSD,H1)       13:25:47        2012.01.02 09:00:00   bar_info[0] = 1.29220000
GL      0       test3 (GBPUSD,H1)       13:25:47        2012.01.02 09:00:00   bar_info[1] = 1.29987000
OJ      0       test3 (GBPUSD,H1)       13:25:47        2012.01.02 09:00:00   bar_info[2] = 1.29591000
FR      0       test3 (GBPUSD,H1)       13:25:47        2012.01.02 09:00:00   Ask=1.29722  Bid=1.29709  

и

JP      0       test3 (GBPUSD,H1)       13:26:07        2012.01.02 09:00:00   bar_info[0] = 1.29591000
PN      0       test3 (GBPUSD,H1)       13:26:07        2012.01.02 09:00:00   bar_info[1] = 1.29987000
KD      0       test3 (GBPUSD,H1)       13:26:07        2012.01.02 09:00:00   bar_info[2] = 1.29220000
MP      0       test3 (GBPUSD,H1)       13:26:07        2012.01.02 09:00:00   Ask=1.29722  Bid=1.29709  

配列内の順序は変更されるが、結果は変更されない。ビッドが配列の最大[0]番目のバーより大きい場合

 
ilunga:
ArraySetAsSeriesは動的配列のみ

正直言って覚えていません。しかし、上に引用したコードの結果は、我々が得たものと一致しています(EURの場合、オープン価格は1.24516 GBPの場合、1.56721です)。

High = SymbolInfoDouble(symbol,SYMBOL_BIDHIGH);

そうですね、現時点ではArraySetAsSeriesがなくても問題なく動きますが

//+------------------------------------------------------------------+
//Function BUY_pending
bool BUY_pending(string symbol,ENUM_TIMEFRAMES period,double volume,ulong magic = 0)
{
//----------------------------------------------------------------------------//
//Work variables
double price = 0, sl = 0, tp = 0; //Prices: Open, Sell stop, Take profit
int ResCopy = -1; //Result of copying the data into an array
int Dig     = 0;  //Digits

double bar_info[1];

bool Result = true; //Returned importance
//----------------------------------------------------------------------------//

ResetLastError();

//Checking the signal to stopping the trading system
  if(IsStopped()) return(false);
//Preparation of structures
ZeroMemory(TradeRequest);
ZeroMemory(TradeResult);
ZeroMemory(CheckResult);
//Copying the data into an array
ResCopy = CopyHigh(symbol,period,0,1,bar_info);

  if(ResCopy==-1)return(false); 
//Calculations
Dig   = (int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);

price = NormalizeDouble(bar_info[0] + 500*_Point,Dig);

追記

つまり、現在のバーを取得したい場合、この行で無駄に3本のバーを配列にコピーしているのです。

//Это не правильно
int ResCopy = CopyHigh("EURUSD",PERIOD_D1,0,3,bar_info);
//так правильно
int ResCopy = CopyHigh("EURUSD",PERIOD_D1,0,1,bar_info);

//если PERIOD_D1 не меняется вот идеальный вариант
 High = SymbolInfoDouble(symbol,SYMBOL_BIDHIGH);
 
Interesting:

追記

例えば、現在のバーを取得する必要がある場合は、絶対にこの行の3つのバーを配列にコピーしてください。

ありがとうございました。このオプションはエラーなく動作し、この場合、十分な性能を発揮します。


しかし、上記のような疑問が残るのは、どうしてBidが最大値より大きくなるのか、ということです =(

 

ilunga:

しかし、上記のような疑問が残るのは、どうしてBidが最大値より大きくなるのか、ということです =(

まず、この最大値がどの期間でとられたものかを判断する必要がある。

配列が double bar_info[n] と宣言されている場合、その中の現在のバーが最大のインデックスとなる。

n = 2の場合、このコードは昨日の日足で動作します。

int ResCopy = CopyHigh("EURUSD",PERIOD_D1,0,2,bar_info);
price = NormalizeDouble(bar_info[0] + 500*_Point,Dig);

と、現在のバーを使ったこの

int ResCopy = CopyHigh("EURUSD",PERIOD_D1,0,2,bar_info);
price = NormalizeDouble(bar_info[1] + 500*_Point,Dig);

例えば、複数のバーをコピーした場合、現在のバーを取得するために以下のようにアレンジする必要があります(ただし、配列にコピーされたバーの 数を確認する必要があるかもしれません)。

price = NormalizeDouble(bar_info[ResCopy-1] + 500*_Point,Dig);
Документация по MQL5: Доступ к таймсериям и индикаторам / Bars
Документация по MQL5: Доступ к таймсериям и индикаторам / Bars
  • www.mql5.com
Доступ к таймсериям и индикаторам / Bars - Документация по MQL5
 
Interesting:

まず、この最大値をどの期間でとるかを定義する。

配列が double bar_info[n] と宣言されている場合、その中の現在のバーが最大のインデックスと なる。

したがって、前ページに3つの要素の配列があるコードが あります。Printで出力すると、Bid = 1.29709となり、bar_info[n-1]には1.29220が格納されます。