mql4语言的特点、微妙之处以及技巧 - 页 34

 
我注意到以下问题:如果你运行一个脚本,它崩溃了(关闭了平台),那么在脚本运行时,日志文件不会保存记录,这使得检测代码中的错误相当困难。我以前没有注意到这个问题。它一直是这样的吗(没有保存记录)?
 

在MT4中似乎没有办法知道(不重新连接)账户上的杠杆是否已经改变。

 
fxsaber #:

在MT4中似乎没有办法知道(不重新连接)账户中的杠杆是否发生了变化。

我大约在五年前就这样做了。客户的杠杆率在某些时间被降低,而在变量AccountInfoInteger(ACCOUNT_LEVERAGE)中并没有变化。而且他需要知道这件事。

我不知道这是否科学,但我已经决定,有一种账户杠杆很少变化,而有一种符号杠杆可能每天变化数次。
我是这样检查的。

//+------------------------------------------------------------------------------------------------------------------+
//| Проверяет изменение плеча и сообщает если это было
//+------------------------------------------------------------------------------------------------------------------+
void leverageCheck()
{
  if(MarketInfo(Symbol(), MODE_MARGINREQUIRED) == 0) return;

   // --- получаем текущее плечо из маржинальных требований, стоимости пункта, тек.котировки
  double leverageSymb = MarketInfo(Symbol(),MODE_TICKVALUE) * Bid / MarketInfo(Symbol(),MODE_MARGINREQUIRED) / Point;
  leverageSymb = int(MathRound(leverageSymb));
  
   // --- если плечо по символу стало меньше на 10% плеча по счету отметим это
  if(leverageSymb < percVar(AccountInfoInteger(ACCOUNT_LEVERAGE), -10))
  {
    string txt = TimeToString(TimeCurrent()) + " Leverage is reduced 1:" + (string)leverageSymb;
    Print(txt, " but account leverage = " + (string)AccountInfoInteger(ACCOUNT_LEVERAGE));

    // --- вывод информации на график
  }
}

//+-------------------------------------------------------------------------------------------------------------------+
//| Получает переменную, увеличивает или уменьшает его на переданный процент и возвращает новое значение
//| Чтобы уменьшить, нужно передать percent с минусом
//+-------------------------------------------------------------------------------------------------------------------+
double percVar(double var, double percent)
{
  return var*(1 + percent/100);
}


有时通过leverageSymb 符号计算的当前杠杆可能会给出199、198而不是200(当杠杆为1:200时)。因此,我不得不从标准杠杆中减去一定的百分比,然后与这个值进行比较。上面的解决方案在当时很有帮助,它可能会派上用场。

 
Vasiliy Pushkaryov #:

我大约在五年前就这样做了。一个客户在某些时间段降低了杠杆率,而在AccountInfoInteger(ACCOUNT_LEVERAGE)变量中却没有任何变化。而且他需要知道这件事。

我不知道是否科学,但我已经决定,有一种账户杠杆很少变化,有一种符号杠杆可能每天变化几次。
我是这样检查的。


有时通过leverageSymb 符号计算的当前杠杆可能会给出199、198而不是200(当杠杆为1:200时)。因此,我不得不从标准杠杆中减去一定的百分比,然后与这个值进行比较。那么,上面的解决方案帮助,可能会派上用场。

是的,跟踪符号的保证金要求是没有问题的。ACCOUNT_LEVERAGE - 只重新连接。

 

通过在票据列表中记住所需的订单来过滤交易历史是非常常见的做法。然后在该列表上SELECT_BY_TICKET。

我从来没有见过一个变体,不是票子而是位置被记住了。以下是性能的比较。

#include <MT4Orders.mqh> // https://www.mql5.com/ru/code/16006
#include <fxsaber\Benchmark\Benchmark.mqh> // https://www.mql5.com/ru/code/31279

int Filter( TICKET_TYPE &Tickets[], int &Pos[] )
{
  const int Total = OrdersHistoryTotal();            

  ArrayResize(Tickets, Total);
  ArrayResize(Pos, Total);
  
  int Amount = 0;

  for (int i = 0; i < Total; i++)
    if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) && (OrderProfit() > 0))
    {
      Tickets[Amount] = OrderTicket();
      Pos[Amount] = i;
      
      Amount++;
    }
    
  ArrayResize(Tickets, Amount);
  ArrayResize(Pos, Amount);
  
  return(Amount);
}

template <typename T>
double Func1( int TypeSelect, const T &Array[] )
{
  double Res = 0;
  const int Total = ArraySize(Array);
  
  for (int i = 0; i < Total; i++)
    if (OrderSelect(Array[i], TypeSelect, MODE_HISTORY))
      Res += OrderProfit();
      
  return(Res);
}

void OnStart()
{   
  TICKET_TYPE Tickets[];
  int Pos[];

  Print(Filter(Tickets, Pos));
  
  const double Res1 = _B(Func1(SELECT_BY_TICKET, Tickets), 1); // Так делают почти все.
  const double Res2 = _B(Func1(SELECT_BY_POS, Pos), 1);        // Не встречал.
  
  Print(Res1);
  Print(Res2);
}


2021.10.11 01:37:08.254 Test19 EURUSD.rann,M1: 561002.61
2021.10.11 01:37:08.254 Test19 EURUSD.rann,M1: 561002.61
2021.10.11 01:37:08.254 Test19 EURUSD.rann,M1: Alert: Bench_Stack = 0, 1 <= Time[Test19.mq4 49 in OnStart: Func1(SELECT_BY_POS,Pos)] = 2827 mcs.
2021.10.11 01:37:08.251 Test19 EURUSD.rann,M1: Alert: Bench_Stack = 0, 1 <= Time[Test19.mq4 48 in OnStart: Func1(SELECT_BY_TICKET,Tickets)] = 7460 mcs.
2021.10.11 01:37:08.244 Test19 EURUSD.rann,M1: 35936

我们看到,门票变体在性能上几乎损失了三倍。

 
fxsaber #:

可以看出,门票变体在性能上几乎损失了三倍。

如果一个仓位被关闭/打开,票据的逻辑不会中断,仓位的逻辑则可能中断。

 
TheXpert #:

如果一个仓位被关闭/打开,票据的逻辑不会中断,仓位的逻辑可能会中断。

这只是关于MODE_HISTORY模式。

 

从理论上讲,这段代码是否有可能错过一些在调用函数 之前和之后存在的顺序?还是会算两次。

double GetLots()
{
  double Lots = 0;
  
  for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS))
      Lots += OrderLots();
      
  return(Lots);
}

也就是说,当一个订单被删除或在枚举期间出现时,索引会发生什么?

 
fxsaber #:

否则就会计算两次。

如果我们假设默认按时间或票据排序,新的订单会出现在列表的最后,从逻辑上讲,当最旧的订单被删除后,所有的订单都会被转移。

事实证明,当从列表的开头删除一个订单时,列表中的一个可以被考虑两次。 这似乎很容易解决--只要记住前一次通过的票,然后进行比较(但仍然不能保证)。

如何在回程通行证上获得通行证--未想明白

 
Andrei Trukhanovich #:

如果我们假设默认按时间或票据排序,新的订单会出现在列表的最后,从逻辑上讲,当最旧的订单被删除后,所有的订单都会被转移。

事实证明,当从列表的开头删除一个订单时,列表中的一个可以被考虑两次。 这似乎很容易解决--只要记住前一次通过的票,然后进行比较(但仍然不能保证)。

如何在回程通行证上获得通行证--还没有想出办法

谢谢你的详细答复!所以我现在想知道如何在一个时间内完成所有的订单。

原因: