任何菜鸟问题,为了不给论坛添乱。专业人士,不要路过。没有你就无处可去 - 6. - 页 641

 
simpleton:

为什么要模拟一个错误?

错误--它是一个信号,表明由于某些与系统限制/故障有关的原因,该算法不能被执行,也不能以某种(当然是有限的,但是--)保证获得结果。FillAndPrint()函数只是雄辩地显示了错误情况的含义和不含义。当发生错误时,它甚至不尝试打印结果。如果没有错误,结果就可以信任。这就是错误/无错误逻辑的构建方式。

你需要在这里修改算法:你需要应用一个额外的过滤器。

这就是应该做的。

首先,我们通过对象类型和参数进行 "过滤",从所有可用的对象中只选择我们需要的对象,然后我们再应用一个额外的过滤器。这大致是一个人的做法。这就是一个人要做的事,对吗?

对于每个这样的小子任务,最好有一个单独的函数。

表达式中不应该有数字,除非在非常特殊的情况下,例如你需要翻倍,而且算法的本质就是这样做。那么数字2就可以直接在表达式中使用。而在其他这种非常罕见的情况下。

在其他情况下,应使用助记符。首先,它们极大地提高了对某地情况的了解,因此有助于减少犯错的机会。其次,数值本身是在一个地方定义的,必要时很容易改变它,与在算法中不止一次使用该数字的情况相比,将不可能犯错,如果不使用助记符,你必须在算法的几个地方固定数字。

运行的结果。

没有发现任何一个物体。将两个助记符的值增加10倍,达到36000(10小时),然后再次运行。

一个趋势已经 "通过 "了过滤。现在让我们把第一个助记符的值恢复到3600,然后运行。

可以看出,这两种趋势现在都已 "通过 "过滤。顺便说一下,我建议用这种方式调试程序的所有分支(部分),而不是任何一个分支。

为了在某种程度上帮助正式化,我将尝试这样解释。该方案显然像一个计划。

每个主要的计划项目都可以分解成较小的子计划项目。小的变成更小的。最小的子计划的项目被直接执行。

每个计划、子计划,甚至最小的子计划都对应着程序中的功能。最小的子计划中的项目对应于只调用系统函数的 "结束 "函数,甚至根本不调用这些函数,例如,AddValue()或DiffInSecs()就是上面讨论的例子。上面的子计划项目对应于调用实现下面子计划项目的函数。在上面讨论的中,这些是MassTrendNumber(), AddValueIfFound(), AddValueIfFiltered()。"低级 "函数不应调用 "高级 "函数,而 "高级 "函数基本上不应向下跳几级,即只应调用基本上在下面一级的函数。这一规则对 "低级 "比对 "高级 "要严格得多。

试着把你的程序组织成由这种树状结构连接的(短)函数,在谁调用谁的意义上建立你的程序。

这个程序有一棵退化的树:一个分支会 "分支 "好几次。而且它的 "分支 "不是两个小分支,而是一个。但可以看到 "高级 "函数持续调用 "低级 "函数这一点。在这次修改中,我在这个结构中又插入了一个层次,一个 "非分支"--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




这是不对的!报价的价值并不重要!而最小刻度线的值必须从当前的价格 计算出来!这等于TICK_VALUE!以上是我代码中的一个例子。
 
borilunad:

borilunad:

这是不对的!报价的价值是不相关的! 而min.tick的值应该从当前价格计算出来!这等于TICK_VALUE!以上是我代码中的一个例子

这怎么会错呢?Marketinfo返回的数值与我上面给出的公式相同。这些公式不是我发明的,它们是终端用来计算TickValue的)))。

很明显,从Marketinfo取值更方便,但他问的是公式或计算方法。

关于我之前写的数值,这并不重要,因为在5 位数的计算中,一个点=10个点,与4位数的点是一样的。

 
evillive:

这怎么会错呢?Marketinfo返回的数值与我上面给出的公式相同。这些公式不是我发明的,它们是终端用来计算TickValue的)))。

很明显,从Marketinfo取值更方便,但他问的是公式或计算方法。

我之前写过关于信号度的问题,这并不重要,因为在5位数上,一个点=10个点,而这是4位数上的同一个点。


这就是我所说的MarketInfo(Symbol(),MODE_TICKVALUE) =1.0/Bid;也许只适用于欧洲美元,我没有在其他货币上喷过!
 
borilunad:

这就是我所说的MarketInfo(Symbol(),MODE_TICKVALUE) =1.0/Bid;也许,只适用于欧元,不适用于其他国家!

根据帮助中给出的定义,这正是欧洲美元的问题所在

MODE_TICKVALUE

16

证券价格 在存款货币中的最小变化


而它的意思是,要多多益善

模式_POINT

11

报价货币中的点的大小。对于当前的符号被存储在预定义的变量Point中



MODE_LOTSIZE

15

以工具的基础货币计算的合同规模


当然,如果你的账户是欧元,你应该使用欧元作为基础货币,但对于拥有美元账户的交易者(他们最常这样做),上述公式是有效的。因为主要的和交易量最大的货币对是以美元为基础的,这些公式最常被使用。

 
evillive:

根据帮助中给出的定义,这是完全错误的。

MODE_TICKVALUE

16

符号价格在存款货币中的最小变化


这意味着这个值应该乘以

模式_POINT

11

报价货币中的点的大小。对于当前的符号被存储在预定义的变量Point中



MODE_LOTSIZE

15

以工具基础货币计算的合同规模


当然,如果你的账户是欧元,你应该使用欧元,但大多数交易者都有一个美元账户。


那么,我有一个特殊的情况,但对于生活在欧元区的我来说,用欧元进行所有的计算是比较方便的!
 

先生们,请给我一个以下指标的代码例子。我搞不清楚需要多少个缓冲区,什么类型的映射,在哪里,以及应该为它们规定什么属性。

该指标如下。

1 栅栏至少每隔三分之一和相邻的栅栏连接。这条线是红色的。

2 杆段连接每5个和相邻杆段的最大值。这条线是蓝色的。

最主要的是:各段没有任何交集。每段的开始和结束都独立于其他段。

该指标计算每段的开始和结束的数值。它们应该根据条件的不同而呈现出不同的颜色。

大致上应该是这样的


 

还有一个问题。

我不能在调试模式下 使用该指标,这是否正常?

当程序到达停止点时,MT4终端挂起,窗口变成白色(在HP中),因此无法看到图表上绘制的内容。

 
Top2n:

下面是准备好的代码。

任务:搜索趋势线(OBJ_TREND),在一个数组中记录相对于当前条形的价格值。具有与对象时间参数的存在有关的过滤功能(OBJ_TREND)。

simpleton非常感谢你,你让我感觉到了正确的代码!)(虽然我不太明白))))

如果你练习,理解就会到来,越来越多。这需要集中精力和专心致志。当程序算法被涂抹在一个大的功能上时,就很难集中精力和专心致志地实现它--形成太多的链接。但是,如果一个程序被划分为功能完整的部分(小功能),对每个独立的小功能进行这样的处理就容易得多。因此,在每个职能层面都是如此。顺便说一下。

   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,也就是允许的最小值,而不是最大值。