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

 
fxsaber:

交易脚本中可以有哪些OnTradeTransaction?不是在你的代码中,而是在别人的交易脚本中。
你真的相信一个成熟的交易机器人可以用脚本来写吗?
 
朋友们,让我们更接近主题:我想看看这个或那个声明的实施例子。不一定是代码,如果有大量的代码,你可以描述逻辑,例如,发送请求以确保它被发送,看那里,如果我们得到这样那样的返回代码,做这样那样的事情。即获取数据的最可靠方式的例子。

否则,如果我们争论,我们会从有用的话题变成几页的争吵。然后我们要把它全部清理干净,留下它的精华......确切地说,我想知道这个或那个过程的本质。让某些东西的实现有几个版本。将有可能讨论每种方法的优点和缺点。

然后,当积累了足够多不同的有用信息后,就有了将其全部积累到一个表中的想法。并在积累下一个有用的筹码时不断补充。
我想这对每个人都会有帮助。
 
问题:如何将一个数字转换成八进制和十六进制系统。

答案。
1.

关于交易、自动交易系统和测试交易策略的论坛

8和16里卡

Taras Slobodyanik, 2017.02.24 22:16

string DecToHex(int n)
  {
   string s = "", c;
   while(n != 0)
     {
      if(n%16<10)
         c=CharToStr(n%16+'0');
      else
         c=CharToStr(n%16+'A'-10);
      s = c + s;
      n = n / 16;
     }
   return(s);
  }
2.

关于交易、自动交易系统和测试交易策略的论坛

8和16里卡

Maxim Kuznetsov, 2017.02.24 22:20

突然,StringFormat,PrintFormat :-)

PrintFormat("Hex %x and octal %o",1122,1122)。
3.

关于交易、自动交易系统和测试交易策略的论坛

8和16里卡

fxsaber, 2017.02.24 22:21

string NumToString( uint Num, const uint Scale = 10 )
{
  static const string digits[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
                                  "A", "B", "C", "D", "E", "F", "G", "H", "I", "K",
                                  "L", "M", "N", "O", "P", "Q", "R", "S", "T", "V", "X", "Y", "Z"};
  
  string Str = (Num == 0) ? "0" : "";
  
  while (Num > 0)
  {
    Str = digits[Num % Scale] + Str;
    
    Num /= Scale;
  }
  
  return(Str);
}

void OnStart()
{
  Print(NumToString(123, 8));
  Print(NumToString(123, 16));
}



 
娼者。
你真的相信一个成熟的交易机器人可以用脚本来写吗?
你可以
 
阿列克谢-科齐岑

把对fxsaber和prostotrader同志的讨论移到另一个主题,如果这里有讨论,这个主题将失去实际意义。当他们想出一个真正的解决方案时,他们会在这里发布。而在我看来,这不应该是怀疑或研究的一个分支。它应该是一个实际解决方案的分支。如果有几个人对这个问题有不同的看法--就让他们在其他地方讨论吧。

<要删除的帖子

让我们让真相被发现。我有时间考虑了一下,决定把它贴出来,而我询问并要求消除我的疑虑的Vitya(维宁)也建议发帖讨论(证实了我对删除的疑虑)--让人们发现真相。我认为这将是正确的做法。反正我以后也要开始制表了,所以当它填满的时候,我可以把它贴在这里。
 
娼者。

你不需要等待几毫秒的时间。

该信息将在OnTradeTransaction 中出现

见代码

你的信息的重点是什么?它将在OnTradeTransaction()中到达,所以呢? 这意味着我们必须等待事件。我们还是要等待。fxsaber的意思是,在OrderSend()被执行后,所执行的动作的信息不会立即出现在终端。有些人喜欢等待OnTradeTransaction(),而有些人则喜欢在列表中看到订单或交易。以下是与MT4的区别,作为一个例子。在M4中,在OrderSend()之后,订单已经在订单列表中,而在OrderClose()之后,订单一直在历史中。

 
阿尔乔姆-特里什金
让我们让真相被发现。我有时间想了想,决定离开它,我问了又问的维提亚(Vinin)也建议离开讨论(证实了我对删除的怀疑)--让真理诞生。我认为这将是正确的做法。我打算以后开始制表,当它填满时就在这里公布。
在与prostotrader的争论中,可能不会出现真相,这不是他开始争论的原因。像往常一样,他甚至不知道自己在说什么。
 
到底有什么样的争论呢?这里没有争议。fxsaber提醒我们,终端的一个功能确实没有记录,每个人真的需要知道,否则在开发EA 时就会出现问题,你将不得不在以后发现并清理。
 
阿尔乔姆-特里什金
让我们发现真相......

Artyom!

你是一个通情达理、政治正确的人!

什么真相?你完全知道我们在说什么。

fxsaber写了一个剧本(还不错),但没有人称赞它,所以他

试图在每个主题中提醒它。

干得好!

但问题来了,你不能在这个脚本中使用OnTradeTransaction,所以他必须从 "OnTradeTransaction先生 "那里 "滚球"(如睡眠或其他计时器)。

当然,还要 "关心 "其他用户,他们还不知道SCRIPT比COUNTER好。

德米特里-费多塞耶夫 总是反对我说的话,不管我是对还是错。

在这里不能找到真理,因为它不是一个原因,而是一个个人的原因,这一点凸显出来。

 
class ORDERSEND  
{
private:
  static const bool IsTester;
  
  static bool Waiting( const bool FlagInit = false )
  {
    static ulong StartTime = 0;

    const bool Res = FlagInit ? false : (::GetMicrosecondCount() - StartTime < ORDERSEND::OrderSend_MaxPause);

    if (FlagInit)
      StartTime = ::GetMicrosecondCount();
    else if (Res)
      ::Sleep(0);

    return(Res);
  }

  static bool EqualPrices( const double Price1, const double Price2, const int digits)
  {
    return(::NormalizeDouble(Price1 - Price2, digits) == 0);
  }

  static bool HistoryDealSelect( MqlTradeResult &Result )
  {
    if ((Result.deal == 0) && (Result.order != 0))
    {
      if (::HistorySelectByPosition(::HistoryOrderGetInteger(Result.order, ORDER_POSITION_ID)))
        for (int i = ::HistoryDealsTotal() - 1; i >= 0; i--)
        {
          const ulong DealTicket = ::HistoryDealGetTicket(i);

          if (Result.order == ::HistoryDealGetInteger(DealTicket, DEAL_ORDER))
          {
            Result.deal = DealTicket;

            break;
          }
        }
    }

    return(::HistoryDealSelect(Result.deal));
  }

#define TMP_ORDERSEND_BENCHMARK(A) \
  static ulong Max##A = 0;         \
                                   \
  if (Interval##A > Max##A)        \
  {                                \
    ORDERSEND_BENCHMARK            \
                                   \
    Max##A = Interval##A;          \
  }

  static void OrderSend_Benchmark( const ulong Interval1, const ulong Interval2 = 0 )
  {
    #ifdef ORDERSEND_BENCHMARK
      TMP_ORDERSEND_BENCHMARK(1)
      TMP_ORDERSEND_BENCHMARK(2)
    #endif // ORDERSEND_BENCHMARK

    return;
  }

#undef TMP_ORDERSEND_BENCHMARK

#define WHILE(A) while ((!(Res = (A))) && ORDERSEND::Waiting())

public:
  static uint OrderSend_MaxPause; // максимальное время на синхронизацию в мкс.
  
  // Полностью синхронизированный с торговым окружением OrderSend.
  // По окончании работы ГАРАНТИРОВАННО и за МИНИМАЛЬНОЕ время доступно корректное торговое окружение.
  // По скорости ничем не уступает связке OrderSendAsync + OnTradeTransaction.
  // Учтены MT5-нюансы: Result.deal == 0, STATE_STARTED и STATE_MODIFY pending.
  // В тестере/оптимизаторе производительность равна штатной OrderSend.

  static bool OrderSendSync( const MqlTradeRequest &Request, MqlTradeResult &Result )
  {
    const ulong StartTime1 = ::GetMicrosecondCount();

    bool Res = ::OrderSend(Request, Result);

    const ulong Interval1 = ::GetMicrosecondCount() - StartTime1;

    const ulong StartTime2 = ::GetMicrosecondCount();

    if (Res && !ORDERSEND::IsTester && (Result.retcode < TRADE_RETCODE_ERROR) && (ORDERSEND::OrderSend_MaxPause > 0))
    {
      Res = (Result.retcode == TRADE_RETCODE_DONE);
      ORDERSEND::Waiting(true);

      if (Request.action == TRADE_ACTION_DEAL)
      {
        WHILE(::HistoryOrderSelect(Result.order))
          ;

        Res = Res && (((ENUM_ORDER_STATE)::HistoryOrderGetInteger(Result.order, ORDER_STATE) == ORDER_STATE_FILLED) ||
                      ((ENUM_ORDER_STATE)::HistoryOrderGetInteger(Result.order, ORDER_STATE) == ORDER_STATE_PARTIAL));

        if (Res)
          WHILE(ORDERSEND::HistoryDealSelect(Result))
            ;
      }
      else if (Request.action == TRADE_ACTION_PENDING)
      {
        if (Res)
          WHILE(::OrderSelect(Result.order) && ((ENUM_ORDER_STATE)::OrderGetInteger(ORDER_STATE) == ORDER_STATE_PLACED))
            ;
        else
        {
          WHILE(::HistoryOrderSelect(Result.order))
            ;

          Res = false;
        }
      }
      else if (Request.action == TRADE_ACTION_SLTP)
      {
        if (Res)
        {
          bool EqualSL = false;
          bool EqualTP = false;

          const int digits = (int)::SymbolInfoInteger(Request.symbol, SYMBOL_DIGITS);

          if ((Request.position == 0) ? ::PositionSelect(Request.symbol) : ::PositionSelectByTicket(Request.position))
          {
            EqualSL = ORDERSEND::EqualPrices(::PositionGetDouble(POSITION_SL), Request.sl, digits);
            EqualTP = ORDERSEND::EqualPrices(::PositionGetDouble(POSITION_TP), Request.tp, digits);
          }

          WHILE((EqualSL && EqualTP))
            if ((Request.position == 0) ? ::PositionSelect(Request.symbol) : ::PositionSelectByTicket(Request.position))
            {
              EqualSL = ORDERSEND::EqualPrices(::PositionGetDouble(POSITION_SL), Request.sl, digits);
              EqualTP = ORDERSEND::EqualPrices(::PositionGetDouble(POSITION_TP), Request.tp, digits);
            }
        }
      }
      else if (Request.action == TRADE_ACTION_MODIFY)
      {
        if (Res)
        {
          bool EqualSL = false;
          bool EqualTP = false;
          bool EqualPrice = false;

          const int digits = (int)::SymbolInfoInteger(Request.symbol, SYMBOL_DIGITS);

          if (::OrderSelect(Result.order))
          {
            EqualSL = ORDERSEND::EqualPrices(::OrderGetDouble(ORDER_SL), Request.sl, digits);
            EqualTP = ORDERSEND::EqualPrices(::OrderGetDouble(ORDER_TP), Request.tp, digits);
            EqualPrice = ORDERSEND::EqualPrices(::OrderGetDouble(ORDER_PRICE_OPEN), Request.price, digits);
          }

          WHILE((EqualSL && EqualTP && EqualPrice))
            if (::OrderSelect(Result.order) && ((ENUM_ORDER_STATE)::OrderGetInteger(ORDER_STATE) != ORDER_STATE_REQUEST_MODIFY))
            {
              EqualSL = ORDERSEND::EqualPrices(::OrderGetDouble(ORDER_SL), Request.sl, digits);
              EqualTP = ORDERSEND::EqualPrices(::OrderGetDouble(ORDER_TP), Request.tp, digits);
              EqualPrice = ORDERSEND::EqualPrices(::OrderGetDouble(ORDER_PRICE_OPEN), Request.price, digits);
            }
        }
      }
      else if (Request.action == TRADE_ACTION_REMOVE)
        if (Res)
          WHILE(::HistoryOrderSelect(Result.order))
            ;
    }

    const ulong Interval2 = ::GetMicrosecondCount() - StartTime2;

    Result.comment += " " + ::DoubleToString(Interval1 / 1000.0, 3) + " + " + ::DoubleToString(Interval2 / 1000.0, 3) + " ms";

    ORDERSEND::OrderSend_Benchmark(Interval1, Interval2);

    return(Res);
  }

#undef WHILE
};

static const bool ORDERSEND::IsTester = (::MQLInfoInteger(MQL_TESTER) || ::MQLInfoInteger(MQL_OPTIMIZATION) ||
                                         ::MQLInfoInteger(MQL_VISUAL_MODE) || ::MQLInfoInteger(MQL_FRAME_MODE));

static uint ORDERSEND::OrderSend_MaxPause = 1000000; // максимальное время на синхронизацию в мкс.

// Эта строчка позволяет сделать все OrderSend корректными.
#define OrderSend ORDERSEND::OrderSendSync

一切都被刻意包裹在教室里,以减少潜在问题的数量。

使用

OrderSend(Request, Result); // Все так же, как со штатной OrderSend

也就是说,要使所有的OrderSend 与交易环境同步,避免陷阱,只需将这段源代码写成mqh-file,并在程序中使用相应的#include即可。