文章 "轻松快捷开发 MetaTrader 程序的函数库(第 二十一部分):交易类 - 基准跨平台交易对象" - 页 3

 
Artyom Trishkin:
如果需要比较交易请求和头寸,最简单的方法是设置头寸标识符(不是魔法)。每个请求都有自己的标识符。顾问的魔法可以对所有仓位保持一致。然后通过标识符(写在仓位或订单的魔法中,永远不会丢失),您可以随时准确匹配请求和仓位/订单。

是这样吗?

交易请求:

ulong order_magic = m_engine.SetCompositeMagicNumber(m_magic, 0, 0, m_order_id);
bool submit_ok    = m_engine.PlaceBuyLimit(m_lot_size, m_symbol, m_entry, m_hard_stop, m_ratio_target, order_magic, m_comment, m_expiry);

事件处理程序:

void CMyRobot::EngineEventHandler(int event_id, const long &lparam, const double &dparam, const string &sparam, bool testing, long chart_id)
{
   if (sparam != m_symbol) return;                                                  //--- 如果符号不匹配,则跳过事件处理

   if (event_id > SERIES_EVENTS_NO_EVENT && event_id < SERIES_EVENTS_NEXT_CODE) {   //--- 处理时间序列事件
      if (event_id == SERIES_EVENTS_NEW_BAR) {                                      // "新栏 "事件: lparam = period | dparam = date/time
         this.RefreshAllIndicators(1);
         this.ExecuteFSM(1, chart_id);                                              // 执行有限状态机(注意:新条形图的索引 = 1)
      }
   }
   else
   if (event_id > TRADE_EVENT_NO_EVENT && event_id < TRADE_EVENTS_NEXT_CODE) {      //--- 处理交易事件
      CArrayObj *event_list = m_engine.GetListAllOrdersEvents();                    // 获取交易事件列表
      if (event_list == NULL) return;
      
      //--- 计算相对于列表末尾的事件索引移位
      //--- 反向测试时,移位值将通过 "lparam "参数传递给事件处理程序
      //--- 在正常操作中,交易事件会逐一发送,并在 OnChartEvent() 中处理
      int shift = testing ? (int)lparam : 0;
      CEvent *event = event_list.At(event_list.Total() - 1 - shift);
      if (event == NULL || event.GetPendReqID() != m_order_id) return;
      
      switch (event.TypeEvent())
      {
         case TRADE_EVENT_PENDING_ORDER_PLASED:                                     //--- 挂单
            if (m_state_curr == FSM_PENDING_ORDER && m_ticket == WRONG_VALUE)
                m_ticket = event.TicketOrderEvent();
            break;
      
         // ...
      }
   }
}
 

问题:上面我需要的CEvent::GetPendReqID() 方法是 保护!!有没有更好的办法,让我不用修改 DoEasy 源代码?依我之见,这些方法应该是公共的;-)

class CEvent : public CObject
  {
//...
protected:
//--- 返回 (1) 指定的神奇数字、(2) 第一组的 ID、(3) 第二组的 ID、(4) 来自神奇数字值的待处理请求。
   ushort            GetMagicID(void)                          const { return ushort(this.Magic() & 0xFFFF);                                 }
   uchar             GetGroupID1(void)                         const { return uchar(this.Magic()>>16) & 0x0F;                                }
   uchar             GetGroupID2(void)                         const { return uchar((this.Magic()>>16) & 0xF0)>>4;                           }
   uchar             GetPendReqID(void)                        const { return uchar(this.Magic()>>24) & 0xFF;                                }
//...
};
 
Dima Diall :

问题:上面我需要的CEvent::GetPendReqID() 方法是 保护!!有没有更好的办法,让我不用修改 DoEasy 源代码?依我之见,这些方法应该是公共的;-)

你需要注意 CEngine 类 - 只有它允许用户程序访问库。

所有其他类都是为了满足库的需要,而不是为用户准备的,但库服务函数 除外,这些函数在将库连接到程序后可在程序中使用。

 
Artyom Trishkin:

您需要观察 CEngine 类,只有它才允许用户程序访问库。

所有其他类都是为了满足图书馆的需要,而不是为用户准备的,但图书馆服务功能 除外,这些功能在将图书馆连接到程序后可在程序中使用。

能给我举一个例子吗?我正在查看CEngine 类,发现它可以提取事件列表、检查其类型等......因此,我可以访问每个事件,但却找不到任何明显的方法来从 CEngine 对象 读取包含在神奇数字(组和请求 ID)中的具体事件详细信息--在我看来,我仍然需要直接从CEvent 对象实例中读取这些信息,就像我在上面的事件处理程序示例中的机器人偶数处理程序方法一样,即CEvent:GetPendReq()

class CEngine
  {
//...
//...
//--- 返回 (1) 订单、交易和头寸事件列表,(2) 按索引排列的基本交易事件对象和 (3) 新交易事件的数量
   CArrayObj           *GetListAllOrdersEvents(void)                    { return this.m_events.GetList();                     }
   CEventBaseObj       *GetTradeEventByIndex(const int index)           { return this.m_events.GetTradeEventByIndex(index);   }
   int                  GetTradeEventsTotal(void)                 const { return this.m_events.GetTradeEventsTotal();         }
//-- 重置上次交易事件
   void                 ResetLastTradeEvent(void)                       { this.m_events.ResetLastTradeEvent();                }
//--- 返回 (1) 最后交易事件、(2) 账户属性中的最后事件和 (3) 符号属性中的最后事件
   ENUM_TRADE_EVENT     LastTradeEvent(void)                      const { return this.m_last_trade_event;                     }
   int                  LastAccountEvent(void)                    const { return this.m_last_account_event;                   }
   int                  LastSymbolsEvent(void)                    const { return this.m_last_symbol_event;                    }
//--- 返回 (1) 对冲账户、(2) 测试器中的工作、(3) 账户事件、(4) 符号事件和 (5) 交易事件标志
   bool                 IsHedge(void)                             const { return this.m_is_hedge;                             }
   bool                 IsTester(void)                            const { return this.m_is_tester;                            }
   bool                 IsAccountsEvent(void)                     const { return this.m_accounts.IsEvent();                   }
   bool                 IsSymbolsEvent(void)                      const { return this.m_symbols.IsEvent();                    }
   bool                 IsTradeEvent(void)                        const { return this.m_events.IsEvent();                     }
//...
//...
  };
 
Dima Diall :

Не могли бы вы привести мне пример?CEngine и вижу, что можно извлечь список событий, проверить их тип и т.Д.,Поэтому я могу получить доступ к каждому событию, но не нахожу очевидного способа прочитать конкретные детали события、пакованные в магическое число (группы и идентификатор запроса)из объекта CEngine - как я вижу, мне все еще нужно читать эту информацию непосредственно изэкземпляров объектаCEvent、 как в моем примере обработчика событий выше в методе обработчика четных событий моего робота, то естьCEvent :: GetPendReqID ()

请稍候。在 ru-segment 中的下一篇文章中,我将尝试解释顾问的问题。

 
Artyom Trishkin:

请稍等一下。ru-segment 的下一篇文章将是关于顾问的,我会在那里尝试解释。

好的,谢谢