文章 "利用 MQL5 面向对象编程法编写"EA 交易"" - 页 2

 
Yedelkin:
如果开盘时的买入价为 1.2695,那么我们已经自动损失了 5 个点。如果同时根据开发者的想法,止损点为 50 点,那么在触发止损之前,还需要向不利方向移动 45 点。也就是说,当触发止损时,买入价不应在 1.2645,而应在 1.2650;卖出价则分别在 1.2655。

1.关于开盘时损失 5 点。

说的损失是对的,如果我们在同一时刻(有条件地)平仓,我们将损失与价差相同的金额,也就是 5 点。

因为多头是以买入价(反向价)平仓的。

至少从逻辑上讲,在这种情况下我们应该得到这个损失(而且是正确的)。

用反向订单平仓也是如此。如果反向订单在 1.2695 的价格(也就是目前的买入价)被触发,您认为我们会得到什么结果?

您不会说 SHORT 仓位的开仓价是 Ask 吧?

2.让我们来处理 BU 平仓

我们还记得,我们在买入价 1.27 开仓(这个价格现在是我们的 BU 水平)。

我们可以合理地假设,如果买入价达到 1.27(即正好上涨 5 个点),BU 平仓就会发生。

让我们借助反向订单在 CU 上平仓来验证我们的假设。这种头寸的开仓价应该是 1.27,而我们知道卖出订单是按买入价下达的。目前买入价为 1.2695。因此,要在 BU 平仓,需要超过 5 点,所以计算没有错误,声明是正确的。

3. 关于 SL 和 TP

这里有两种说法:

а.多头以 Ask 开仓,以 Bid 收仓;空头以 Bid 开仓,以 Ask 收仓。

б.到 TP 和 SL 的距离根据开仓价计算,计算时考虑头寸的方向。


我们将完全按照第二条陈述,确定我们例子中的 SL 和 TP 价格。在开仓价 1.27 时,SL = 1.2650,TP = 1.28(根据上述条件)。

根据第一条陈述,多头(本例中为多头)将在卖出价等于 1.27(买入价等于 1.2695,基于 5 个点的点差)的条件下开盘。

现在我们来确定在什么条件下会触发我们的止损和止赢。

当满足其中一个条件时,我们的头寸将被平仓(如果没有其他因素):

关于 TP - 如果买价达到 1.28(比 1.27 高 100 点),此时卖价将为 1.2805(第一条声明和价差大小规则)。

让我们通过使用反向头寸在 TP 上平仓来验证我们的陈述。 这种头寸的开盘价应为 1.28,我们知道卖单是按买价下达的。目前买价为 1.2695。因此,要在 TP 上平仓,就必须通过 5 点(弥补差价损失)+ 100 点来固定利润。

在 SL 上 - 如果价格达到 SL 水平,即我们记忆中的 1.2650。


现在我们来了解一下是什么价格。从逻辑上讲,应该是买入价(对应于反向订单的开盘价)。

我们记得,目前(根据开仓条件)买入价是 1.2695。因此,在触发 SL 之前,价格需要超过 45 点。

因此,我们的损失将等于点差(5 点)+ 45 点,即价格在触发止损前需要经过的时间。

从这个角度来看,您是对的

让我们用反向头寸平仓来验证我们的说法。 这种头寸的开盘价应为 1.2650,而我们知道卖单是以买入价开仓的。目前买入价为 1.2695。因此,若要以卖出价平仓,必须超过 45 点。当触发止损单时,将损失 50 个点(5 个点的点差+ 45 个点的反向波动)。

PS

但从这个角度来看,我对 MQL4 的这个示例不是很清楚。

int ticket;

  if(iRSI(NULL,0,14,PRICE_CLOSE,0)<25)
    {
     ticket=OrderSend(Symbol(),OP_BUY,1,Ask,3,Bid-25*Point,Ask+25*Point,"My order #"+counter,16384,0,Green);
     if(ticket<0)
       {
        Print("OrderSend failed with error #",GetLastError());
        return(0);
       }
    }

更确切地说,我不太清楚 SL 是根据什么逻辑和什么语句考虑的。

但根据这个示例(也只是根据这个示例),我得出以下结论

//基本示例
ticket=OrderSend(Symbol(),OP_BUY,1,Ask,3,SL = Bid-Loss*Point,TP = Ask+Profit*Point,"My order #"+counter,16384,0,Green);
//下单开设市场头寸
ticket=OrderSend(Symbol(),OP_BUY,1,1.27,3,1.2645 = 1.2695-50*Point,1.28 = 1.27+100*Point);

根据 Open = 1.27、SL = 1.2645 和 TP = 1.28 的值,我理解如下:

1.当 Ask 达到 1.27 的价格(在我们的例子中已经达到了)时开仓;

2.2. BU 水平位于 1.27 价格,为了在该水平上平仓,货币符号(在我们的情况下为欧元)的汇率应增加点差大小(在我们的情况下为 5 点);

3.3. 开仓时,我们会立即损失点差金额(在我们立即平仓的情况下),因为根据逻辑语句,开仓应使用反向订单平仓。在 MQL4 代码中,这种操作如下

//基本示例
ticket=OrderSend(Symbol(),OP_SELL,1,Bid,3,0,0);
//在市场上以反向订单平仓
ticket=OrderSend(Symbol(),OP_SELL,1,1.2695,3,0,0);

4.从逻辑上讲,这应该是买入价,因为反向订单是在这个价格打开的(当买入价达到 1.28 时,交易执行)。据此,MQL4 代码中的平仓应如下所示

//使用市场订单(反向订单)关闭 TP 仓位
ticket=OrderSend(Symbol(),OP_SELL,1,1.28,3,0,0);
//使用反挂单(限制器)平仓
ticket=OrderSend(Symbol(),OP_SELLLIMIT,1,1.28,3,0,0);

5.当交易符号(在本例中为欧元)的汇率从开仓时下跌 50 点后,将触发 SL。


现在,最有趣的事情是

让我们根据 MQL4 帮助中的相同示例(一个经典示例,可能有成千上万的人使用过)来检查市场头寸的开仓情况。

我们将使用以下代码进行检查

//+------------------------------------------------------------------+
double PriceOpen,PriceSL,PriceTP;
int ticket;
//+------------------------------------------------------------------+
/为订单制定价格
PriceOpen = Ask;
PriceSL   = Bid-500*Point;
PriceTP   = PriceOpen+1000*Point;
//下单开设市场头寸
ticket = OrderSend(Symbol(),OP_BUY,0.10,PriceOpen,5,PriceSL,PriceTP);
//+------------------------------------------------------------------+

在 Alpari 服务器上执行此代码(使用真实报价),结果如下

2010.08.24 09:12:47 '******': instant order buy 0.10 EURUSD at 1.26292 sl: 1.25776 tp: 1.27292

很容易猜到,在这种情况下,我们将得到以下大小 SL = 516(或 4 位数 51 点) TP = 1000(或 4 位数 100 点)

PPS

让我们看看 MQL4 帮助

参数:
符号 - 执行交易操作的金融工具名称。
cmd - 交易操作。可以是任何交易操作 值。
交易量 - 手数。
价格 - 开盘价。
滑点 - 市场订单(买入或卖出订单)的最大允许价格偏差。
止损 - 达到亏损水平时的头寸收盘价(无亏损水平时为 0)。
止盈 - 达到盈利水平时的头寸收盘价(无盈利水平时为 0)。
注释 - 订单注释文本。注释的最后部分可由交易服务器更改。
魔法 - 订单的魔法编号。可用作用户定义的标识符。
到期 - 挂单的有效期。
箭头颜色 - 图表上开盘箭头的颜色。如果没有该参数或其值为 CLR_NONE,则图表上不显示开盘箭头。
例如
  int ticket; if(iRSI(NULL,0,14,PRICE_CLOSE,0)<25) { ticket=OrderSend(Symbol(),OP_BUY,1,Ask,3,Bid-25*Point,Ask+25*Point, "My order #"+counter,16384,0,Green); if(ticket<0) { Print("OrderSend failed with error #",GetLastError()); return(0); } } } }

"兄弟,告诉我真相在哪里?"......?

OrderSend - Документация на MQL4
  • docs.mql4.com
OrderSend - Документация на MQL4
 
Yedelkin:

我不明白代码的以下部分:

// 将上一栏(第 1 栏)的收盘价复制到相应的 Expert Advisor 变量中
   Cexpert.setCloseprice(mrate[1].close);  // 栏 1 收盘价
//--- 检查是否有买入头寸
   if (Cexpert.checkBuy()==true)
   {
      if (Buy_opened) 
         {
            Alert("我们已经有了一个购买位置!!"); 
            return;    // 不增加多头头寸
         }
      double aprice = NormalizeDouble(latest_price.ask,_Digits);
      double stl    = NormalizeDouble(latest_price.ask - STP*_Point,_Digits);
      double tkp    = NormalizeDouble(latest_price.ask + TKP*_Point,_Digits);
      int    mdev   = 100;
      // 下订单
      Cexpert.openBuy(ORDER_TYPE_BUY,Lot,aprice,stl,tkp,mdev);
   }
如果我们要建立一个买入头寸,我们应该关注 latest_price.ask 价格,但在为该头寸设置止损和止盈时,我们应该关注 latest_price.bid 价格。这样做对吗?为什么在代码文本中,止损和止盈都是根据卖出价设置的?是打印错误还是特定策略的特殊性(代码中也有类似的卖出建仓结构)?

这部分代码应根据以下陈述来理解:

а.多头 - 以卖出价开仓,以买入价平仓;空头 - 以买入价开仓,以卖出价平仓;

б.头寸通过反向指令平仓;

в.BU 水平为开仓价;

г.到 TP 和 SL 的距离从开仓价(CU 水平)计算;

д.当买入价达到等于开仓价 + 利润大小的水平时,TP 将被触发;

e.当证券价格达到买入价等于开仓价-亏损额时,将触发卖出价。

Expert Advisor 的作者很可能在其工作中遵循了类似的声明。为了尽可能清楚地说明一切,我借助以下屏幕(我们感兴趣的是红色矩形)对上述内容进行说明。


 
Interesting:

e.当买入价达到等于开仓价-亏损额的水平时,将触发止损单。

谢谢,我明白了。但是,根据 "e "点,当触发止损时,买入价不应在 1.2645,而应在 1.2650;卖出价应在 1.2655。

 
Yedelkin:

谢谢,我明白了。但是,根据 "e "点,当触发止损时,买入价不应在 1.2645,而应在 1.2650;卖出价应在 1.2655。

可能是这样,您需要检查市场触发止损时到底会发生什么(或者根据所有可用的收盘可能性调整矩阵模型)....。


关于 "e "点(我的理解是)

如果我理解正确,在从开仓(卖出)开始计算的情况下,将是 1.27-50 = 1.2650(价格将超过 45 点,姿势将关闭)。在这种情况下,我认为止损点应在买价 1.2650 和卖价 1.2655 上。

还有一点,如果我们从买入价开始计算,那么我们将得到 1.2695-50 - 1.2645 的价格(数学不容争辩)。如果我们从买入价开始计算止损,我们将得到 1.27-1.2645 = 55 点(据我所知,这并不是我们计划的一部分)。

PS

至少,这个模型可以让我们从开仓价(在我看来是正确的)正确突破止损价和止盈价位......

当然,如果能听到开发人员对实际价格计算方法(不仅是 SL 和 TP)的官方意见,那将会非常有趣。

 

问题


100 美元是卢布还是美元?;)

 
承诺会消失。
 
Jager:

问题


100 美元是卢布还是美元?;)

这是以毫秒为单位的超时值。该参数已从所有交易功能中删除。
 

你好,感谢你提供了一个很好的例子。

但我想问一下,这样做对吗?

在 EA 中,它在每个新的条形图开始时检查交易机会。

在类函数 getbuffers() 中,它检索了从当前条形图 0 开始的最近 3 个条形图的数据,而当前条形图 0 刚刚形成,因此数值是错误的。

void MyExpert::getBuffers()
{
if(CopyBuffer(ADX_handle,0,0,3,ADX_val)<0 || CopyBuffer(ADX_handle,1,0,3,plus_DI)<0
|| CopyBuffer(ADX_handle,2,0,3,minus_DI)<0 || CopyBuffer(MA_handle,0,0,3,MA_val)<0)

是否应该从位置 1 开始检索最近 3 个条形图的指标数据?

谢谢

 

伟大的文章,塞缪尔

感谢您提供这篇无价之宝、

根据这篇文章,我们可以在类中加入 IsNewBar 或 Buy_opened 等函数,然后从 EA 中调用这些函数

再次感谢您、

希望能看到你的更多文章、

哈迈德

 

请帮我弄明白一些我不明白的东西:

在 EA 的最开始,函数被调用

  Cexpert.doInit(ADX_Period,MA_Period);
при этом для ее корректного выполнения требуются уже установленные параметры symbol  и period :
//+-----------------------------------------------------------------------+
// 我们类的公共函数 
//+-----------------------------------------------------------------------+
/*
 初始化
*/
void MyExpert::doInit(int adx_period,int ma_period)
{
   //--- 获取 ADX 指标句柄
   ADX_handle=iADX(symbol,period,adx_period);
  //--- 获取移动平均线指标句柄
   MA_handle=iMA(symbol,period,ma_period,0,MODE_EMA,PRICE_CLOSE);
однако, заполнение этих параметров конкретными значениями происходит позже, уже после Cexpert.doInit :
//--- 启动初始化功能
   Cexpert.doInit(ADX_Period,MA_Period);
//-- 为我们的类对象设置所有必要的变量
   Cexpert.setPeriod(_Period);     // 设置周期
   Cexpert.setSymbol(_Symbol);     // 指定符号(货币对)
   
   Никак не пойму, как может правильно выполниться Cexpert.doInit, если переменной symbol пока не присвоено
значение (или как-то присвоено ?) Застрял тут и дальше никак . Спасибо.