有谁知道如何开发一个多货币指标? - 页 3

 
4x_Gypsy:

最大的线索是 "但我不知道怎么做"。

OP没有作出任何回应,这表明有什么问题。我的 "猜测 "是OP因为缺乏理解而感到沮丧,并放弃了这个话题。几年前有一段时间,我也做过同样的事情。我从不同的网站/论坛学到的东西比这个多,因为没有人花时间意识到我是多么的新,并且不断地发布例子,进行完全超出我当时理解的讨论。

从你的观点来看,你可能是对的,但另一方面,我也看到了许多问题,如果只是冒然看一下文件,这些问题就会得到回答,你真的觉得自己是个傻瓜,一次又一次地回答这些问题。

此外,这里还有谷歌和一个搜索选项。如果我不知道如何做某事,这是我的下一步,我试图自己解决这个问题。

在这个主题的情况下,我不知道如何编码一个多货币系统,我会回答谷歌或在这里搜索已有的代码。

 
gooly:

从你的观点来看,你可能是对的,但另一方面,我看到了许多问题,如果只是冒险看一下文件,这些问题就会有答案,你真的觉得自己是个傻瓜,一次又一次地回答这些问题。

此外,这里还有谷歌和一个搜索选项。如果我不知道如何做某件事,这是我的下一步,试图自己解决这个问题。

在这个主题的情况下,我不知道如何编码一个多货币系统,我会回答谷歌或搜索这里已经存在的代码。

谢谢你的反馈,很高兴它是积极的。

对于我在这种情况下的表现,我对谁都感到抱歉。我确实是一个热爱和平、没有戏剧性的人,通常会忽略大多数我不同意的事情。

 

大家好。

很抱歉长时间没有在这里活动。我正在出差,也忙于一些项目,不得不把项目搁置一段时间。

在看了帖子的更新后,我有一些观点需要澄清。

  1. 我不希望有人为我编码所有的东西,只需要给我指出正确的方向,剩下的我来做。好吧......我现在将测试WHRoeder的解决方案,并做我的东西,稍后将在这里发布结果。WHRoeder建议:https://www.mql5.com/en/forum/158938
  2. 在创建这个主题之前,我已经搜索了类似的帖子,但没有找到......然后创建这个主题。
  3. 我很抱歉花了很长时间来回应,但我真的工作过度了,但现在我正在继续研究这个指标。
  4. 对不起,我的英语不好! 我的语言是葡萄牙语,当我发布英语时,需要使用谷歌翻译,它并不完美。


 
这是我的测试。

只需让用户通知他们的资产,然后显示所有交易的高/低值。

如果,任何一个选择的货币对与活动窗口相同,他的汇率就会正常更新。但其他货币对只显示指标添加时的汇率......而不再更新......

正如你在下图中看到的,指标被添加到GBPUSD窗口中......并且GBPUSD的汇率被逐点更新。但欧元兑美元没有更新,仍然是相同的值。

抄送率


下面是指标代码。

//+------------------------------------------------------------------+
//|                                                MultiCurrency.mq4 |
//|                         Copyright 2016, Wemerson Couto Guimarães |
//|                  https://www.mql5.com/pt/users/wemersonrv/seller |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Wemerson Couto Guimarães"
#property link      "https://www.mql5.com/pt/users/wemersonrv/seller"
#property version   "1.00"
#property strict
#property indicator_separate_window

input string UsePairs="EURUSD,GBPUSD"; // Pares separados por vírgula.

struct pair_struct{
   string symbol;
   MqlRates rates[];
};
pair_struct pairs[];
bool initial;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit(){
   int i=0, j=0, c;
   string _pairs[], msg="";
   bool pairok=false;
   initial = true;
   ENUM_INIT_RETCODE result = INIT_SUCCEEDED;
   
   StringSplit(UsePairs, StringGetCharacter(",",0), _pairs);
   
   for( i=0; i< ArraySize(_pairs); i++){
      pairok=false;
      
      for( j=0; j<SymbolsTotal(true); j++){
         if( SymbolName(j, true) == _pairs[i]){
            pairok=true;
            break;
         }
      }
      if( pairok ){
         c=ArraySize(pairs);
         ArrayResize(pairs, c+1);
         pairs[c].symbol = _pairs[i];
      }else{
         msg += _pairs[i] + ", ";
      }
   }
   if( msg != "" ){
      string invalids = ArraySize(pairs)== 1?"Invalid Pair: ": "Invalid Pairs: ";
      msg = invalids +  StringSubstr(msg,0,StringLen(msg)-2) + ". Please Check!";
      Alert(msg);
      result = INIT_PARAMETERS_INCORRECT;
   }else{
      for(i=0; i<ArraySize(pairs); i++){
         ArrayCopyRates( pairs[i].rates, pairs[i].symbol, PERIOD_CURRENT );
      }
   }   
   
   return(result);

}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){
   
   Comment("");
   
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {

   int i=0;
   if( initial ){
      for( i=0; i<ArraySize(pairs); i++){
         if(pairs[i].rates[0].time == 0) return(rates_total);
      }
      initial=false;
   }
   
   string log="";
   
   for(i=0; i<ArraySize(pairs); i++){
      log += "\nPair: " + pairs[i].symbol + 
             " - High: "+ DoubleToStr(pairs[i].rates[0].high, Digits()) + 
             " - Low: "+ DoubleToStr(pairs[i].rates[0].low, Digits());
   }

   Comment( "\n\n*** Pair Rates***\n" + log );
   return(rates_total);
   
}
//+------------------------------------------------------------------+

 
我试着用RefreshRates(),但结果还是一样......只有同一窗口的那一对在工作,其他的对没有更新。
 
wemersonrv:
我尝试使用RefreshRates(),但仍然有相同的结果......只有在同一窗口的那一对可以工作,其他对不更新。

RefreshRates()MqlRates 数据没有关系。WHRoeder的 示例代码只对Pre-600版本有效。对于最新的版本,你需要检查我的帖子中提到的各点,比如测试ArrayCopyRates() 的返回代码,以及错误代码,费率数组的大小,以及作为WHRoeder 指出的附加预防措施,时间属性的有效性。

PS!如果你在英语方面有困难,请给我发个邮件。我是葡萄牙人(葡萄牙)。

 

大家好。

在测试中,我在OnCalculate函数 中加入了 "重新复制 "费率的功能......通过添加一个循环,首先在所有迭代中释放数组对,然后再次复制费率。看起来是有效的,并且没有返回错误。

我不知道这是否是实现我所需要的最好方法,但显然它是有效的,而且没有错误。


   int i=0;
   if( initial ){
      for( i=0; i<ArraySize(pairs); i++){
         if(pairs[i].rates[0].time == 0) return(rates_total);
      }
      initial=false;
   }

   // My change to recopy rates every tick by adding a loop at starting of OnCalculate() to do this
   // AS FMIC says, ArrayCopyRates needs the array without content, 
   // then before recopy, free the array.
   for(i=0; i<ArraySize(pairs); i++){
      ArrayFree(pairs[i].rates);
      ArrayCopyRates(pairs[i].rates, pairs[i].symbol, PERIOD_CURRENT);
   }
 
wemersonrv: 在测试中,我在OnCalculate函数中加入了 "重新复制 "费率......通过添加一个循环,首先在所有的迭代中释放一对数组,然后再次复制费率。看起来是有效的,并且没有返回错误。
  1. 正如文件 中所述。
    如果从另一个图表中请求数据(符号名称和/或时间框架与当前的不同),情况可能是相应的图表没有在客户终端打开,必须从服务器上请求必要的数据。在这种情况下,错误ERR_HISTORY_WILL_UPDATED (4066 - 所请求的历史数据正在更新中)将被放在last_error变量中,人们将不得不重新请求
    在这里 得到验证
    如果根本没有历史数据,ArrayCopyRates将返回一个错误(ERR_NO_HISTORY_DATA = 4073。)重复调用也会失败,直到下载完成。当有历史记录但不是最新的,ArrayCopyRates返回有效,同时将`_LastError`设置为ERR_HISTORY_WILL_UPDATED (= 4066.)
  2. 测试你的返回代码,如果有必要,可以睡眠和重试。什么是函数的返回值?我如何使用它们?-MQL4论坛MQL4程序中的常见错误以及如何避免这些错误 - MQL4文章
 

给关注这个话题的人一个更新

我一直在通过PM帮助OP修复他的代码,因为他在英语方面有困难,而我们都讲葡萄牙语。在我们的测试中,我们遇到了另一个发生在"ArrayCopyRates()"函数中的 "趣事"。当在EA中用"ArrayCopyRates()"使用MqlRates 数组时,数据数组是一个虚拟数组,总是报告事物的当前状态,所以数据总是新鲜的。

然而,在一个指标中,情况似乎不是这样的。数组不是一个虚拟副本,而是在调用"ArrayCopyRates()"时设置的一个静态副本。当符号与图表符号不同时,数据不会更新。当它与图表符号相同时,那么数组数据是 "活的",并按预期更新,但当它是另一个符号时,它是一个静态拷贝。

因此,为了使其在指标中工作,如果需要新的数据,必须在每次调用OnCalculate()事件时调用 "ArrayCopyRates()"函数。

 

大家好。

  • FMIC,感谢您的支持
  • WHRoeder,也谢谢你......你总是为我们大家服务!。
  • 感谢所有论坛成员的考虑,甚至感谢在这个主题中产生的整个辩论。这是非常有趣的。

这(几乎)是我后来做的同样的事情,但不同的是我在ArrayCopyRates之前运行ArrayFree...而且我没有做你帮助我的验证。

这里是FMIC帮助我的最终代码。它现在在一个指标代码中正常工作..:

input string UsePairs="NZDCAD,EURUSD,GBPUSD,USDJPY"; // pairs separated by commas
struct pair_struct{
   string symbol;
   MqlRates rates[];
   bool valid;
};
pair_struct pairs[];
bool initial;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit(){
   
   int i=0, j=0, c;
   string _pairs[], msg="";
   bool pairok=false;
   initial = true;
   ENUM_INIT_RETCODE result = INIT_SUCCEEDED;
   
   StringSplit(UsePairs, StringGetCharacter(",",0), _pairs);
   
   for( i=0; i< ArraySize(_pairs); i++){
      pairok=false;
      
      for( j=0; j<SymbolsTotal(true); j++){
         if( SymbolName(j, true) == _pairs[i] ){
            pairok=true;
            break;
         }
      }
      if( pairok ){
         c=ArraySize(pairs);
         ArrayResize(pairs, c+1);
         pairs[c].symbol = _pairs[i];
         pairs[c].valid = false;
      }else{
         msg += _pairs[i] + ", ";
      }
   }
   if( msg != "" ){
      string invalids = ArraySize(pairs)== 1?"Invalid Pair: ": "Invalid Pairs: ";
      msg = invalids +  StringSubstr(msg,0,StringLen(msg)-2) + ". Please Check!";
      Alert(msg);
      result = INIT_PARAMETERS_INCORRECT;
   }
   return(result);

}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){
   
   Comment("");
   
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {

   InitializeRates();
   
   int i=0;
   string log="";
   for(i=0; i<ArraySize(pairs); i++){
      log += "\nPar: " + pairs[i].symbol;
      if( pairs[i].valid ){
         log += " - Time: "+ TimeToString( pairs[i].rates[0].time ) + 
                " - Open: "+ DoubleToString( pairs[i].rates[0].open, (int)MarketInfo( pairs[i].symbol, MODE_DIGITS ) ) +
                " - Close: "+ DoubleToString( pairs[i].rates[0].close, (int)MarketInfo( pairs[i].symbol, MODE_DIGITS ) ) +
                " - High: "+ DoubleToString( pairs[i].rates[0].high, (int)MarketInfo( pairs[i].symbol, MODE_DIGITS ) ) +
                " - Low: "+ DoubleToString( pairs[i].rates[0].low, (int)MarketInfo( pairs[i].symbol, MODE_DIGITS ) );
      }else{
         log += " - Currently not valid!";
      }
   }

   Comment( "\n\n*** Pair Rates***\n" + log );
   return(rates_total);
   
}
//+------------------------------------------------------------------+

void InitializeRates(){
 
   for( int i=0; i<ArraySize( pairs ); i++ ){
      pairs[i].valid = false;
      ResetLastError();
      if( ArrayCopyRates(pairs[i].rates, pairs[i].symbol, PERIOD_CURRENT) > 0 ){
         if( _LastError == 0 ){
            if( ArraySize(pairs[i].rates) > 0 ){
               if( pairs[i].rates[0].time > 0 )
                  pairs[i].valid = true;
            }
         }
      }
   }

}