程序库: MT4Orders - 页 19

 
Jeka77769:

您好!说明中写道:"因此,在 MT5 的 SELECT_BY_TICKET 模式下,OrderSelect 在极少数情况下(在测试器中)可能无法选择 MT4 中预期的内容。"您能详细说明具体是哪种情况吗?

当仓位/交易/订单票据匹配时。

 
跨平台代码的另一个示例(说明

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

智能交易系统:eaBreakeven

fxsaber, 2018.01.11 08:13 pm.

#include <MT4Orders.mqh>     //https://www.mql5.com/zh/code/16006
#include <Price_Compare.mqh> //https://www.mql5.com/zh/code/16169

input int    Breakeven           = 15;           //盈亏平衡点
input int    Distance            = 5;            //从仓位开仓价计算的以点为单位的盈亏平衡距离
input int    MagicNumber         = 16112017;     //神奇数字
input bool   EnableSound         = true;         // 设置盈亏平衡时,启用/禁用播放声音
input string SoundFile           = "alert1.wav"; //声音文件名

void OnTick()
{
  DoBreakeven();
}

double GetNewStopLoss()
{
  const double point = SymbolInfoDouble(OrderSymbol(), SYMBOL_POINT);  
  const double stop_level = SymbolInfoInteger(OrderSymbol(), SYMBOL_TRADE_STOPS_LEVEL) * point;
  
  const double price_open = OrderOpenPrice();
  const double latest_price = OrderClosePrice();  
  const double stoploss = OrderStopLoss();

  double new_stoploss = 0;
  
  //-- 如果头寸利润大于盈亏平衡点,则将止损移至盈亏平衡点价格 + 距离 
  return(((OrderType() == OP_BUY)  && (CP(latest_price - price_open, point) >= Breakeven * point) &&
                                      (CP(new_stoploss = price_open + Distance * point, point) > stoploss) &&
                                      (CP(latest_price - new_stoploss, point) > stop_level)) ||
         ((OrderType() == OP_SELL) && (CP(price_open - latest_price, point) >= Breakeven * point) &&
                                      ((CP(new_stoploss = price_open - Distance * point, point) < stoploss) || !stoploss) &&
                                      (CP(new_stoploss - latest_price, point) > stop_level))
         ? NormalizeDouble(new_stoploss, (int)SymbolInfoInteger(OrderSymbol(), SYMBOL_DIGITS)) : 0);
}

void DoBreakeven()
{
//如果盈亏平衡为负值,则禁用盈亏平衡功能
  if (Breakeven >= 0)      
  //Loop for positions
    for (int i = OrdersTotal() - 1; i >= 0; i--)
      if (OrderSelect(i, SELECT_BY_POS) && (OrderType() <= OP_SELL) && (!MagicNumber || (OrderMagicNumber() == MagicNumber)))
      {
        const double new_stoploss = GetNewStopLoss();
        
        if (new_stoploss)      
        {
          if (!OrderModify(OrderTicket(), OrderOpenPrice(), new_stoploss, OrderTakeProfit(), OrderExpiration()))
            Print(GetLastError());
          else if(EnableSound)
            PlaySound(SoundFile);
        }
      }
}
 

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

如何更改挂单的交易量?

fxsaber, 2018.01.19 16:34

#include <MT4Orders.mqh> //https://www.mql5.com/zh/code/16006

// 更改挂单的交易量。Async = true - 异步发送订单模式
bool OrderChangeLots( const long Ticket, const double Lots, const bool Async = false )
{
  return(OrderSelect(Ticket, SELECT_BY_TICKET) && (Lots != OrderLots()) && (Async
         ? (OrderDeleteAsync(Ticket) &&
            OrderSendAsync(OrderSymbol(), OrderType(), Lots, OrderOpenPrice(), 0, OrderStopLoss(), OrderTakeProfit(), OrderComment(), OrderMagicNumber(), OrderExpiration()))
         : (OrderDelete(Ticket) &&
            (OrderSend(OrderSymbol(), OrderType(), Lots, OrderOpenPrice(), 0, OrderStopLoss(), OrderTakeProfit(), OrderComment(), OrderMagicNumber(), OrderExpiration()) != -1))));
}

void OnStart()
{
  for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS) && (OrderType() >= OP_BUYLIMIT))
      OrderChangeLots(OrderTicket(), OrderLots() + 1, true);
}
 
MT4 专家顾问写得越好,转换到 MT5 就越容易。转换时,原始 EA 的大小/复杂程度并不重要。

交易、自动交易系统和交易策略测试论坛。

智能交易系统:三点套利

fxsaber, 2018.01.20 09:58

#define  MT4_TICKET_TYPE  // 命令发送(OrderSend)和订单票据(OrderTicket)必须返回与 MT4 相同类型的值 - int。
#include <MT4Orders.mqh> //https://www.mql5.com/zh/code/16006

#define MODE_MARGINREQUIRED 0

//https://www.mql5.com/ru/forum/170952/page9#comment_4134898
// 申请购买 1 个手数所需的自由资金数额
double MarketInfo( const string Symb, const int )
{
  MqlTick Tick;
  double MarginInit, MarginMain;

  return((SymbolInfoTick(Symb, Tick) && SymbolInfoMarginRate(Symb, ORDER_TYPE_BUY, MarginInit, MarginMain)) ? MarginInit * Tick.ask *
          SymbolInfoDouble(Symb, SYMBOL_TRADE_TICK_VALUE) / (SymbolInfoDouble(Symb, SYMBOL_TRADE_TICK_SIZE) * AccountInfoInteger(ACCOUNT_LEVERAGE)) : 0);
}

int DayOfWeek( void )
{
  MqlDateTime sTime = {0};

  TimeToStruct(TimeCurrent(), sTime);

  return(sTime.day_of_week);
}

int Hour( void )
{
  return((int)((TimeCurrent() % (24 * 3600)) / 3600));
}

#include "ThreePoint.mq4"
 
如果出现OnTradeTransaction 允许您编写一个非交易顾问(服务),跟踪账户上运行的交易 "克隆 "顾问是否存在。
 

平仓的 佣金会立即从余额中扣除。

  • 因此,平仓前的净值不会显示平仓后的余额。
  • 这意味着在 MT5 中根本无法计算盈亏平衡。
  • MT4Orders 仍有仓位佣金。因此会出现以下情况

    #include <MT4Orders.mqh>
    
    #define  PRINT(A) Print(#A + " = " + (string)(A))
    
    void OnStart()
    {
      double ProfitWithoutCommission = 0;
      double ProfitWithCommission = 0;  
      
      for (int i = OrdersTotal(); i >= 0; i--)
        if (OrderSelect(i, SELECT_BY_POS))
        {
          OrderPrint();
          
          ProfitWithoutCommission += OrderProfit() + OrderSwap(); // 在不考虑佣金的情况下计算当前利润
          
          ProfitWithCommission += OrderProfit() + OrderSwap() + OrderCommission(); // 计算当前利润,并将佣金考虑在内
        }
            
      PRINT(AccountInfoDouble(ACCOUNT_EQUITY) - AccountInfoDouble(ACCOUNT_BALANCE));
      
      PRINT(ProfitWithoutCommission);
      PRINT(ProfitWithCommission);  
    }


    结果

    #895889 2018.02.08 09:08:26 sell 1.00 EURUSD 1.22807 0.00000 0.00000 1.22877 -6.14 0.00 -70.00 0
    AccountInfoDouble(ACCOUNT_EQUITY)-AccountInfoDouble(ACCOUNT_BALANCE) = -70.0
    ProfitWithoutCommission = -70.0
    ProfitWithCommission = -76.14


    如您所见,净值和余额之间的差额因佣金金额而不同。这样看来,MT4 的经典表述

    ProfitWithCommission += OrderProfit() + OrderSwap() + OrderCommission(); // 计算当前利润,并将佣金考虑在内

    在 MT5 中失去意义。但事实并非如此。事实上,当您平仓时,"余额 "将按此金额变化,而不是之前显示的 "净值"。粗略地说,从 MT4 的概念来看,MT5 中的 Equity 值是错误的。

    考虑到 MT5 的这一特殊性。在这种情况下,资金库会更加准确。而且可以轻松计算出相同的盈亏平衡点。

     

    未平仓头寸的 评论是最基本的。要做到这一点,只需在没有对头寸符号进行注释的情况下进行任何交易即可。

    在所述情况下,库不会丢失注释 - OrderComment() 将生成开仓时的注释。

     
    // 更改列表:
    // 13.02.2018
    // 添加:添加 MT5-OrderSend 错误日志。
    // 修复:现在只有 MT5 平仓订单(SL/TP/SO、部分/全部平仓)是 "不可见 "的。
    // 修复:更正了在订单关闭后确定平仓头寸 SL/TP 的机制 - 在 StopLevel 允许的情况下工作。
     

    这里将详细介绍 MT5 操作的一些特殊性。长期以来,程序库一直在正确地 处理这种情况。但它曾发誓(警报)说这种情况不符合标准。

    现在不会了

    // 更改列表:
    // 15.02.2018
    // 修复:MT5-OrderSend 同步检查现在考虑到了 ECN/STP 实施可能存在的特殊性。


    作为测试,您可以在复杂的模拟账户 FXOpen-MT5 上运行此脚本。

    #include <Debug.mqh> //https://c.mql5.com/3/173/Debug.mqh
    #include <MT4Orders.mqh>
    
    #define Bid (SymbolInfoDouble(_Symbol, SYMBOL_BID))
    #define Ask (SymbolInfoDouble(_Symbol, SYMBOL_ASK))
    
    void OnStart()
    {
      _P(OrderCloseBy(_P(OrderSend(_Symbol, OP_BUY, 1, Ask, 0, 0, 0)), _P(OrderSend(_Symbol, OP_SELL, 1, Bid, 0, 0, 0))));
    }


    结果

    void OnStart(), Line = 9: OrderSend(_Symbol,OP_SELL,1,Bid,0,0,0) = 897247
    void OnStart(), Line = 9: OrderSend(_Symbol,OP_BUY,1,Ask,0,0,0) = 897248
    void OnStart(), Line = 9: OrderCloseBy(_P(OrderSend(_Symbol,OP_BUY,1,Ask,0,0,0)),_P(OrderSend(_Symbol,OP_SELL,1,Bid,0,0,0))) = true
    附加的文件:
    Debug.mqh  1 kb
     

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

    组织循环订单蛮力

    fxsaber, 2018.02.16 09:40

    MT5 做得一点都不好。显示问题的示例

    // 错误读取每个刻度的交易环境示例
    // 脚本模拟 TS 的两个刻度,如果没有刻度,则应打开一个位置。
    
    #include <Trade/Trade.mqh>
    
    // 按字符返回位置数
    int GetAmountPositions( const string Symb )
    {
      int Res = 0;
      
      // 该 MQL5 代码出错
      for (int i = PositionsTotal() - 1; i >= 0; i--)
        if (PositionGetSymbol(i) == Symb)
          Res++;
    
    /*
    // 在 MT4 中,执行此代码不会出错
      for (int i = OrdersTotal() - 1; i >= 0; i--)
        if (OrderSelect(i, SELECT_BY_POS) && (OrderType() <= OP_SELL) && (OrderSymbol() == Symb))
          Res++;
    */      
      return(Res);
    }
    
    // OnTick 示例
    void ExampleOnTick()
    {
      static CTrade Trade;
      
      // 如果没有位置,则打开
      if (!GetAmountPositions(_Symbol))
        Trade.Buy(1);    
    }
    
    // 模拟两个 Tick 事件的到来
    void OnStart()
    {
      ExampleOnTick(); 
      
      Sleep(10); // 两个刻度之间 ~10 毫秒。
      
      ExampleOnTick();
    }

    如果在一个没有头寸的符号上运行此脚本,您认为最终会发生什么?

    正确的答案是会打开一个或两个仓位

    如果您至少部分地使用 MQL4 风格编写脚本,就可以避免这个问题。为了确保这一点,只需使用 MQL4 风格(在源代码中注释)编写 GetAmountPositions,而不使用 MQL5 风格。

    对 MQL5-style 要特别警惕。