新人对MQL4和MQL5的任何问题,对算法和代码的帮助和讨论 - 页 380

 
大家好。
这是我第一次上论坛,如果我在论坛上做错了什么,请提前原谅我。
我正在看带有指标的图表,已经有很长一段时间了。最近我损失了2笔存款。在开立新账户之前,我想在历史上检查策略的盈利能力。我在使用MT4的模拟账户。
我根本就不是一个程序员。我只能在MT4上安装指标,也许可以在MetaEditor中改变指标线的 粗细(我很可能无法在指标代码中改变颜色,只能在终端中改变)。
对于我这样的人来说,你有什么明确的信息,从哪里开始一步步测试(用英语说就是 "指导黑鬼如何使用厕所")?该策略有3个指标:MA(3个简单的指标),具有标准水平的随机指数,以及具有5个水平的CCI。在从上到下越过指标水平后开启空头交易,多头交易反之亦然(我想这很清楚...)。设定取舍和损失。
我希望能在自动模式下直观地跟踪策略,也希望能在没有可视化的情况下选择指标和订单的参数。
 
ZebStamp:
大家好。
这是我第一次上论坛,如果我在论坛上做错了什么,请提前原谅我。
我正在看带有指标的图表,已经有很长一段时间了。最近我损失了2笔存款。我想在开立新账户前根据历史数据检查策略的盈利能力。我在使用MT4的模拟账户。
我根本就不是一个程序员。我只能在MT4上安装指标,也许可以在MetaEditor中改变指标线的 粗细(我很可能无法在指标代码中改变颜色,只能在终端中改变)。
对于像我这样的人,你有什么明确的信息,从哪里开始一步一步地测试(用通俗的英语 "给黑鬼上厕所的说明")?该策略有3个指标:MA(3个简单的指标),具有标准水平的随机指数,以及具有5个水平的CCI。在从上到下越过指标水平后开启空头交易,多头交易反之亦然(我想这很清楚...)。设定取舍和损失。
我希望能在自动模式下直观地跟踪策略,也希望能在没有可视化的情况下选择指标和订单的参数。

当创建一个图形对象(GO),如TrendLine,你选择颜色。当你重新创建TrendLine时,它将以相同的颜色创建。对于Hline来说--你选择一种颜色--接下来就是这样了。以黄色、蓝色、...

如果CS创建了EA、指标、脚本--那么正如你在程序中写的那样。有时参数的选择

 
STARIJ:

如果你认为看你代码的人可以很快发现错误,那你就错了。编译器会寻找错误。程序文本应该是有格式的--MetaEditor有一个样式设计工具。如果你喜欢不同的风格--使用,例如,AStyle.exe程序。经过样式设计,你很快就会发现,程序1)有一个额外的闭合小括号。2)声明的变量: datetime date_Buf_1; //指标日期数组--要使其成为一个数组,必须是[size]或[]的动态数组,然后大小必须设置为ArrayResize,似乎。而且你必须在使用数组之前做这件事--见上面关于这个问题的帖子。3) FileOpen(InpDirectoryName+"//"+InpFileName - 似乎棍子应该向另一个方向倾斜。而且,最好不要使用InpDirectoryName+"//"--反正你会在Files文件夹中找到文件。

行:int copied=CopyTime(NULL,0,0,0,date_Buf_1); 编译器很生气,start=0=0


谢谢。我设法解决了一些问题,但更多的是凭直觉而不是靠理解。但我们仍然有3个关于阵列的错误。

'Buf_1' - 需要数组 111.mq4 93 21

'date_Buf_1' - 数组要求 111.mq4 94 21

'Buf_1' - 需要的阵列 111.mq4 100 16


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
input string             InpFileName="111.csv";      // Имя файла 
input string             InpDirectoryName="Data";     // Имя каталога 

datetime Время=0;   // Время прошлого бара
double Bid1;
double   Buf_1[];
// double ExtBuffer;
long V1; // объем для текущего тика вверх
long V2; // накопленный объем для всех тиков вверх текущего бара
long V3; // объем текущего тика вниз
long V4; // накопленный объем для всех тиков вниз для текущего бара
long V5;  // отрицательные и положительные iVolume нарастающим итогом
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnInit()
  {
   IndicatorDigits(0);
   SetIndexBuffer(0,Buf_1);
//SetIndexBuffer(1,Buf_2);
   Bid1=Bid;
   V5=0;

  }
//+------------------------------------------------------------------+
//| 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[])
  {
   datetime Вр=Time[0];   // Время текущего бара
   if(Вр>Время)           // Если новый бар
     {
      Время=Вр;           // Запомнить
                          //      Buf_1[0]=0;         // и обнулить последний элемент буфера
     }

   datetime date_Buf_1[]; // массив дат индикатора 
   datetime time_Buf_1[]; // массив времени 
                          // --- считаю объем для положительных и отрицательных тиков      
   if(Bid>=Bid1)
     {
      if(Bid>Bid1) // если тик положительный..
        {
         V1=iVolume(NULL,0,0); // если повышающий цену тик, то находим его объем
         V2= V1 + V2;
        }
      else
        {
         V1=0;                // если Bid1 = Bid2, т.е. изменение цены = 0, то iVolume этого тика присваиваем 0;
         V2= V1 + V2;
        }
     }
   else
     {
      V3 = iVolume(NULL, 0, 0); // если понижающий цену тик 
      V4 = V3 + V4;             // то находим его объем  
     }

   V5=V2-V4;               // определяем разницу (дельту) между объемами положительных и отрицательных тиков
   Bid1=Bid;
   Buf_1[0]=V5; // в буфер сгружаем  дельту

                //   ExtBuffer = Buf_1 [0];
//   double macurrent=iMAOnArray(ExtBuffer,0,5,0,MODE_LWMA,0); 

// запись в файл данных буфера


//--- установим для массивов признак таймсерии 
   ArraySetAsSeries(Buf_1[0],true);
   ArraySetAsSeries(date_Buf_1[0],true);

//--- скопируем таймсерию 
   int copied=CopyTime(NULL,0,10000,0,date_Buf_1);

//--- подготовим массив Buf_1 
   ArrayResize(Buf_1[0],copied);

//--- скопируем значения линии индикатора  
   for(int i=0;i<copied;i++)
     {
      Buf_1[i]=V5;
     }
//--- откроем файл для записи значений индикатора 
   ResetLastError();
   int file_handle=FileOpen(InpDirectoryName+"//"+InpFileName,FILE_READ|FILE_WRITE|FILE_CSV);
   if(file_handle!=INVALID_HANDLE)
     {
      PrintFormat("Файл %s открыт для записи",InpFileName);
      PrintFormat("Путь к файлу: %s\\Files\\",TerminalInfoString(TERMINAL_DATA_PATH));
      //--- сначала запишем значения индикатора 
      FileWrite(file_handle,Buf_1[0]);
      //--- запишем время и значения в файл 
      for(int i=0;i<Buf_1[0];i++)
         FileWrite(file_handle,time_Buf_1[0],Buf_1[0]);
      //--- закрываем файл 
      FileClose(file_handle);
      PrintFormat("Данные записаны, файл %s закрыт",InpFileName);
     }
   else
      PrintFormat("Не удалось открыть файл %s, Код ошибки = %d",InpFileName,GetLastError());

   return(rates_total);
  }
//+------------------------------------------------------------------+


我不明白如何落实你的意见。但我发现了一个额外的主食:)
 
YarTrade:

谢谢你。我设法解决了一些问题,但更多的是凭直觉而不是靠理解。但我仍然有3个关于阵列的错误。

'Buf_1' - 需要数组 111.mq4 93 21

'date_Buf_1' - 数组要求 111.mq4 94 21

'Buf_1' - 需要的阵列 111.mq4 100 16



我不明白如何落实你的意见。但我发现了一个额外的托架:)
只留下数组变量的名称。在编译器指向你的那些代码行中删除"[]"。
 
Artyom Trishkin:
只留下变量数组的名称。在编译器指向你的那些代码行中删除"[]"。

谢谢你。我将看看现实生活中会发生什么。我非常怀疑是否会有东西被写入文件 :)

 

出现了一些问题,我非常希望得到您的帮助。我发现了一件非常可悲的事情,EA在测试过程中的表现和实时表现是非常不同的,所以我想分析一下最常见的典型错误。我先写一写我遇到的情况。 如果你能与程序员分享你的经验,知道他应该记住什么,在他的代码中应该保留什么,我将非常感激。

1.除以0的 错误出现在真实交易模式中,尽管代码中没有除以0,而且在回测中也没有发生。程序员通过将每个除数写成NormalizeDouble(x,Digits)来解决这个问题。

2.这笔交易没有开启。周五,当我运行回溯测试时,交易打开了,但在我交易时没有。此外,专家顾问的日志还没有显示任何错误。我不知道这里可能有什么问题,但我有几件事。首先,我得到了 "应检查'ordersend'的返回值 "这样的警告,但如果我理解正确,这应该不会影响代码的执行?还是说这都是滑坡的问题?我的值是1,这不算太小。而我应该进行入市的那根柱子开盘时没有出现缺口。

我从带滑块的标准例子中抽取了 "if(Volume[0]>1)return; "一行,并将其插入到代码的开头。也就是说,我的代码只在新条形图出现时的第一个刻度线上执行。会不会是一个条形图打开后出现了成交量,而我的代码却没有被执行?

4.请告知在使用EA的历史和实时工作时需要注意的事项或典型错误,谢谢。


 
LuckySith:

出现了一些问题,我非常希望得到您的帮助。我发现了一件非常可悲的事情,EA在测试过程中的表现和实时表现是非常不同的,所以我想分析一下最常见的典型错误。我先写一写我遇到的情况。 如果你能与程序员分享你的经验,知道他应该记住什么,在他的代码中应该保留什么,我将非常感激。

1.除以0的 错误出现在真实交易模式中,尽管代码中没有除以0,而且在回测中也没有发生。程序员通过将每个除数写成NormalizeDouble(x,Digits)来解决这个问题。

2.这笔交易没有开启。周五,当我运行回溯测试时,交易打开了,但在我交易时没有。此外,专家顾问的日志还没有显示任何错误。我不知道这里可能有什么问题,但我有几件事。首先,我得到了 "应检查'ordersend'的返回值 "这样的警告,但如果我理解正确,这应该不会影响代码的执行?还是说这都是滑坡的问题?我的值是1,这不算太小。而我应该进行入市的那根柱子开盘时没有出现缺口。

我从带滑块的标准例子中抽取了 "if(Volume[0]>1)return; "一行,并将其插入到代码的开头。也就是说,我的代码只在新条形图出现时的第一个刻度线上执行。会不会是一个条形图打开后出现了成交量,而我的代码没有被执行?

4.请告知需要注意的事项,或在使用历史和实时的EA时的典型错误,谢谢。

用对 "新条 "的正常检查来取代 "if(Volume[0]>1)return; "这样的狂野结构,论坛上有很多这样的例子。

"应该检查'ordersend'的返回值 "这类警告到目前为止还不是错误,它们是未来的潜在错误。代码中不应该有任何警告,在线工作时更不应该有。

"我有1,这不算太少"--这在开盘时可能非常少,特别是在半小时或一小时的开盘时,此时的价差会大大扩大。

我们需要的是:对新的酒吧进行检查,如果是新的,那么观察进入的条件,如果它们重合--做一笔交易。之后,我们必须记录下这个酒吧的工作情况,并等待新的工作。

我们现在有: if(Volume[0]>1) return; =如果有一个新的柱子,我们寻找条件,条件不符合 ==大的价差 =在OnTick()中再次退出,在下一个tick上if(Volume[0]>1) return; 它不会进一步,所以交易已经错过,即使价差是0.0001。

 

你好。请你告诉我如何用代码来描述以下内容。有一个平坦的地方,由上、下水平线 限定。专家顾问会自己检测并设置它们。

我们需要EA检测到价格离开平坦区域,然后返回到这个区域。而后才会开仓。

为了过滤噪音,我使用一个参数为2或3的移动目标

 
Vitaly Muzichenko:

用正常的 "新条 "检查来取代 "if(Volume[0]>1)return; "这样的疯狂结构,论坛上有很多这样的检查。

像 "应该检查'ordersend'的返回值 "这样的警告--这还不是一个错误,这是未来的一个潜在错误。代码中不应该有任何警告,在线工作时更不应该有。

"我有1,这不算太少"--这在开盘时可能非常少,特别是在半小时或一小时的开盘时,此时的价差会大大扩大。

我们需要的是:对新的酒吧进行检查,如果是新的,那么观察进入的条件,如果它们重合--做一笔交易。之后,我们必须记录下这个酒吧的工作情况,并等待新的工作。

我们现在有: if(Volume[0]>1) return; =如果有一个新的柱子,然后看条件,条件不符合 ==大的价差 =在OnTick()中再次退出,在下一个tickif(Volume[0]>1) return; 它不会进一步错过,所以即使价差是0.0001,也会错过交易。


关于开一个新的酒吧。会好吗?:

datetime counted_bar = 0;

int OnInit()
{
   counted_bar = 0; // если нужно, чтоб при перезапуске последний бар был проанализирован
   ...

void OnTick()
{
   // Если появился новый бар
   if ( iTime( _Symbol, _Period, 0 ) > counted_bar )
   {
      counted_bar = iTime( _Symbol, _Period, 0 );

      // Анализируем индикаторы
      ...
   }
 
LuckySith:

关于开一家新酒吧。这是否是一个好的选择?:

最初就让它这样吧。

接下来,我们需要做一个适当的固定,酒吧的工作,但在这里,我们需要计算的整个方法,以TOR。

据我从你的帖子中看到,我们必须这样做。

void OnTick()
{
   // Если появился новый бар
   if ( iTime( _Symbol, _Period, 0 ) > counted_bar )
   {
      // Анализируем индикаторы
      if(SpreadMax > текущий спред) return;

      counted_bar = iTime( _Symbol, _Period, 0 );
      ...
   }

其本质是这样的:如果点差高于正常值,那么我们再次退出OnTick,在一个新的tick上检查点差,如果它是正常的--我们发送一个订单,并记住在这个bar上有一个交易。

也有第二种方法。

void OnTick()
{
   // Если появился новый бар
   if ( iTime( _Symbol, _Period, 0 ) > counted_bar )
   {
      if(SpreadMax > текущий спред) return;
      // Анализируем индикаторы
      ...
      result = OrderSend(...);
      // если открылась позиция, то result будет тикет позиции
       if(result>0) counted_bar = iTime( _Symbol, _Period, 0 );
   }

一般来说,你需要定义逻辑,当它应该记录时,在形成 "新栏 "之前不要再检查。

原因: