dbsx 发表于 2014-8-31 20:07:49

EA历史测试时为什么会先平仓呢?

本帖最后由 dbsx 于 2014-9-7 12:50 编辑

为了避免误会,我把标题内容改了下,意思应该不会再有歧义了。
我现在历史测试时,发现个很奇怪的现象:就是它竟然会先执行平仓的动作---试问,一开始连开仓都没开怎么会平仓呢,平的又是什么仓位?
我这个代码,正常情况下历史测试的开始应该先输出("当前有仓位")、或者("当前无仓位")咯,而且初始化测试的时候应该是无仓位才对咯,结果测试报告是这样的:

也不知道为何这一上来就跳到全部平仓的函数里去了?
---------------------------------------------------------------------------------------------------------------
部分关键代码如下:
void OnTick()
{
   
   if(是否持仓()==true)
   {
   printf("当前有仓位");
    //出场();
    全部平仓(500,500);
   }
else if (是否持仓()==false)
   {
    printf("当前无仓位");
    入场();
   
   }
}


bool 是否持仓()
{
   if (OrdersTotal()>0) return(true);
   else return(false);
}

//------------------------
void 全部平仓(int 买入平仓滑点,int 卖出平仓滑点)//消灭所有单子
{
while(OrdersTotal()!=0)
   {
      printf("要全部平仓咯!");
         for(int i=0;i<OrdersTotal();i++)
         {
             if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true)
               {
                  if(OrderType()==OP_BUY)                           
                  {
                      if(OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_BID),买入平仓滑点)==false) Print("平买单出错:"+IntegerToString(GetLastError()));
                  }
                  if(OrderType()==OP_SELL)
                  {
                      if(OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_ASK),卖出平仓滑点)==false) Print("平卖单出错:"+IntegerToString(GetLastError()));
                  }
                  
                  if(OrderType()>1)//这句话的意思是if((OrderType()==OP_BUYLIMIT)||(OrderType()==OP_SELLLIMIT)||(OrderType()==OP_BUYSTOP)||(OrderType()==OP_SELLSTOP))
                  {
                      if(OrderDelete(OrderTicket())==false) Print("平挂单出错:"+IntegerToString(GetLastError()));
                  }
               }
         }
}   



以下是总结:先谢谢各路大侠的帮助,THANKS A LOT.
由于这帖牵涉的内容确实有点多了,所以还是在这里总结下。
本来呢,一切的一切开端是因我写了个程序,想实现一次一单,同一时间不得有1张以上的单子,结果发现历史测试的日志结果我读不懂。
这个是2014-5-15到2014-8-29的测试结果


像这图,我看不懂这红框里的平仓哪儿来的,这明明没有开仓日志啊,还一直以为是我的写法有问题,于是我在代码里加了很多printf函数,结果也没发现问题所在。后来发现,原来“结果”里是有显示的,早在这日期前就有开仓额操作了:


也就是说,处于某些原因,日志并没有print显示所有的操作内容,但是“结果”是完整的。
----
然后,在这途中,我又发现我的开仓函数“全部平仓”和DIGITS版主提供的“全平”函数有些出入,虽然功能是一样的。
这是我的全部平仓函数:
void 全部平仓(int 买入平仓滑点,int 卖出平仓滑点)//消灭所有单子
{
         for(int i=0;i<OrdersTotal();i++)
         {
             Print("要全部平仓咯!");
             if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true)
               {
                  if(OrderType()==OP_BUY)                           
                  {
                      if(OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_BID),买入平仓滑点)==false) Print("平买单出错:"+IntegerToString(GetLastError()));
                  }
                  if(OrderType()==OP_SELL)
                  {
                      if(OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_ASK),卖出平仓滑点)==false) Print("平卖单出错:"+IntegerToString(GetLastError()));
                  }
                  
                  if(OrderType()>1)//这句话的意思是if((OrderType()==OP_BUYLIMIT)||(OrderType()==OP_SELLLIMIT)||(OrderType()==OP_BUYSTOP)||(OrderType()==OP_SELLSTOP))
                  {
                      if(OrderDelete(OrderTicket())==false) Print("平挂单出错:"+IntegerToString(GetLastError()));
                  }
               }
         }
}      

这是版主提供的全平函数(我稍微修改了下,加了点异常处理输出和数组越界问题处理):
void 全平(int 滑点)
{
int t,k=0;//这里我改了下,不然它提示数组越界;
for(int i=0;i<OrdersTotal();i++)
{
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)==false)
    {
   Print("订单选择错误");
    }
    else
    {
      k=k+1;
      t=OrderTicket();
      Print("全平函数 :",t);
    }
}
if(k!=0)
{
    for(int i=k-1;i>=0;i--)
    {
   if(OrderSelect(t, SELECT_BY_TICKET)==false)
   {
      Print("平仓错误。。。");
   }
   else
   {
   if(OrderType()==OP_BUY)OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_BID),滑点);
   if(OrderType()==OP_BUYSTOP)OrderDelete(OrderTicket(),CLR_NONE);
   if(OrderType()==OP_BUYLIMIT)OrderDelete(OrderTicket(),CLR_NONE);
   if(OrderType()==OP_SELL) OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_ASK),滑点);
   if(OrderType()==OP_SELLSTOP)OrderDelete(OrderTicket(),CLR_NONE);
   if(OrderType()==OP_SELLLIMIT)OrderDelete(OrderTicket(),CLR_NONE);
   }
    }
}
}

其他代码都没变,只是平仓函数替换了下,全部平仓的测试是这样的:


版主的全平函数测试结果是这样的:



从结果来看,是版主的全平函数更加好,但是为什么会有区别我还不清楚。从内部构造来看,我的全部平仓是逐个通过次序取样操作,取一个操作一个;而版主提供的全平函数则是全部取完放入数组再通过订单号一个个取出操作,但至于这个操作的不同为什么会对结果产生不同的效果我还不清楚。why?


最后的结果,我的代码整合了各方的建议,变成了这样,至少这个代码是达到我的要求了。
//+------------------------------------------------------------------+
//|                                                          测试3.mq4 |
//|                        Copyright 2014, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2014, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
#property strict
extern   int 移动止损点数=20;
//+------------------------------------------------------------------+
//| Expert initialization function                                 |
//+------------------------------------------------------------------+
int OnInit()
{
//---
   //Print("初始化全部平仓");
   //全部平仓(500,500);
//---
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
   
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
//---
   if(OrdersTotal()==0)//有单则监控出场行为,
   {
   Print("当前市场中没有单子,入场行为监控中...");
   入场();
      
   }
   else
   {
      Print("当前市场中有"+IntegerToString(OrdersTotal())+"张单子,出场行为监控中...");//所有单子,包括挂单
   出场();
   }
   
}


//+------------------------------------------------------------------+
void 入场()
{
   if(Open>Open && Close>Close && Open>Close)
   {
   下单(0,0.6,30,30,300,"看涨"+IntegerToString(1),1); //0代表看涨
   Print("下买单函数");
   }
   else if (Open<Open && Close<Close && Open<Close)
   {
    下单(1,0.7,30,30,300,"看跌"+IntegerToString(2),2); //1代表看空
      Print("下卖单函数");
   
      
   }   
}
//---------------------------------
void 出场()
{
   for(int i=0;i<OrdersTotal();i++)
   {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
      {
         if(OrderSymbol()==Symbol())
         {
         if(OrderType()<2)//表示持仓的卖单或者买单
          {
         if(OrderType()==OP_BUY)
         {
            Print("买单测试平仓");
            
            if ((Bid - OrderOpenPrice()) > (移动止损点数 * MarketInfo(OrderSymbol(), MODE_POINT)))    //开仓价格 当前止损和当前价格比较判断是否要修改跟踪止赢设置
            {
               Print("买单平仓:1步");
            if (OrderStopLoss() < Bid - 移动止损点数 * MarketInfo(OrderSymbol(), MODE_POINT))
                {
                  Print("买单平仓:2步");
               if(OrderModify(OrderTicket(), OrderOpenPrice(),Bid - 移动止损点数 * MarketInfo(OrderSymbol(), MODE_POINT), OrderTakeProfit(),0)==false)
                  {
                   Print("移损设置出错,错误代码:"+IntegerToString(GetLastError()));
                  }
                }
               
             }
             Print("买单平仓:3步");
            double 移动止损价= Bid - 移动止损点数 * MarketInfo(OrderSymbol(), MODE_POINT);
            int num=iBarShift(OrderSymbol(),0,OrderOpenTime())+2; //定位当前距离开盘中间bar数量+2
            Print("买单平仓:4步");
            if(Bid < Open || Bid <= 移动止损价)
            {
            Print("买单由于bid"+Bid+"<第一跟k线"+Open+"或者Bid≤移动止损价"+移动止损价+"而平仓");
             全平(500);
            }
         }
         
         else if(OrderType()==OP_SELL)
         {
             Print("卖单测试平仓");
            if ((OrderOpenPrice() - Ask) > (移动止损点数 * MarketInfo(OrderSymbol(), MODE_POINT)))    //开仓价格 当前止损和当前价格比较判断是否要修改跟踪止赢设置
            {
            Print("卖单平仓:1步");
            if ((OrderStopLoss()) > (Ask + 移动止损点数 * MarketInfo(OrderSymbol(), MODE_POINT)))
                {
                Print("卖单平仓:2步");
               if(OrderModify(OrderTicket(), OrderOpenPrice(),Ask + 移动止损点数 * MarketInfo(OrderSymbol(), MODE_POINT), OrderTakeProfit(),0)==false)
               {
                  Print("移损设置出错,错误代码:"+IntegerToString(GetLastError()));
               }
                }
            }
            Print("卖单平仓:3步");
            double 移动止损价= Ask + 移动止损点数 * MarketInfo(OrderSymbol(), MODE_POINT);
            int num=iBarShift(OrderSymbol(),0,OrderOpenTime())+2; //定位当前距离开盘中间bar数量+2
            Print("卖单平仓:4步");
            if(Ask > Open || Ask >= 移动止损价)
            {
            Print("卖单由于Ask"+Ask+">第一跟k线"+Open+"或者Ask≥移动止损价"+移动止损价+"而平仓");
            
         全平(500);
            }
         }
          }
          else
          {
            Print("平挂仓");
             全平(500);//如果是挂单的话
          }
         
         
         }
         else Print("当前图表非目标货币对,请调整!");
      }
   }      
}   
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++

int 下单(int 看涨或看跌,double Lots,double 止损点数,double 止盈点数, int 滑点,string comment,int magic)//带有止损止盈功能(不用填0)的买入函数
{
   double 止损价位;
   double 止盈价位;
             if(看涨或看跌==0) //0代表看涨
                {   
                   int ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,滑点,0,0,comment,magic,0,White);
                   if(ticket>0) Print("下买单成功,开始止损止盈");
                   else Print("下买单失败,错误代码:"+IntegerToString(GetLastError()));
                  
                   if(OrderSelect(ticket, SELECT_BY_TICKET)==true) //为了保证止损止盈为0时数字设置准确,需进行如下3个判断.
                      {
                      止损价位=NormalizeDouble(OrderOpenPrice()-MarketInfo(OrderSymbol(),MODE_POINT)*止损点数,Digits);
                      止盈价位=NormalizeDouble(OrderOpenPrice()+MarketInfo(OrderSymbol(),MODE_POINT)*止盈点数,Digits);
                     if((止损点数!=0)&&(止盈点数!=0))
                                 {
                                 //Print("止损价位:"+止损价位+"止盈价位:"+止盈价位);
                                 //Print("1:2个都不为0");
                                 if(OrderModify(OrderTicket(),OrderOpenPrice(),止损价位,止盈价位,0,Red)==false)
                                    {
                                    Print("修改错误,代码:"+IntegerToString(GetLastError()));
                                    }
                                    else Print("订单修改成功");
                                 }
                     if((止损点数==0)&&(止盈点数!=0))
                                 {
                                 //Print("2;第1个为0");
                                 
                                    if(OrderModify(OrderTicket(),OrderOpenPrice(),0,止盈价位,0,Red)==false)
                                       {
                                          Print("修改错误,代码:"+IntegerToString(GetLastError()));
                                       }
                                        else Print("订单修改成功");
                                 }
                     if((止损点数!=0)&&(止盈点数==0))
                                 {
                              // Print("3;第2个为0");
                                    if(OrderModify(OrderTicket(),OrderOpenPrice(),止损价位,0,0,Red)==false)
                                       {
                                          Print("修改错误,代码:"+IntegerToString(GetLastError()));
                                       }
                                        else Print("订单修改成功");
                                 }
                     }
                  return(ticket);   
                   }
               else if(看涨或看跌==1) //1代表看空
                  {
                      int ticket=OrderSend(Symbol() ,OP_SELL,Lots,Bid,滑点,0,0,comment,magic,0,Red);
                      if(ticket>0) Print("下卖单成功,开始止损止盈");
                      else Print("下卖单失败,错误代码:"+IntegerToString(GetLastError()));
                     
                      if(OrderSelect(ticket, SELECT_BY_TICKET)==true) //为了保证止损止盈为0时数字设置准确,需进行如下3个判断.
                        {
                              止损价位=NormalizeDouble(OrderOpenPrice()+MarketInfo(OrderSymbol(),MODE_POINT)*止损点数,Digits);
                              止盈价位=NormalizeDouble(OrderOpenPrice()-MarketInfo(OrderSymbol(),MODE_POINT)*止盈点数,Digits);
                               if((止损点数!=0)&&(止盈点数!=0))
                                 {
                              // Print("止损价位:"+止损价位+"止盈价位:"+止盈价位);
                                 //Print("1:2个都不为0");
                                 if(OrderModify(OrderTicket(),OrderOpenPrice(),止损价位,止盈价位,0,Red)==false)
                                    {
                                    Print("修改错误,代码:"+IntegerToString(GetLastError()));
                                    }
                                    else Print("订单修改成功");
                                 }
                               if((止损点数==0)&&(止盈点数!=0))
                                 {
                              // Print("2;第1个为0");
                                 
                                    if(OrderModify(OrderTicket(),OrderOpenPrice(),0,止盈价位,0,Red)==false)
                                       {
                                          Print("修改错误,代码:"+IntegerToString(GetLastError()));
                                       }
                                        else Print("订单修改成功");
                                 }
                              if((止损点数!=0)&&(止盈点数==0))
                                 {
                              // Print("3;第2个为0");
                                    if(OrderModify(OrderTicket(),OrderOpenPrice(),止损价位,0,0,Red)==false)
                                       {
                                          Print("修改错误,代码:"+IntegerToString(GetLastError()));
                                       }
                                        else Print("订单修改成功");
                                 }
                            }
                         return(ticket);
                        }         
            else return(0);         
}         

///////////////////////////////////////////////////////////////////////////
void 全平(int 滑点)
{
int t,k=0;//这里我改了下,不然它提示数组越界;
for(int i=0;i<OrdersTotal();i++)
{
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)==false)
    {
   Print("订单选择错误");
    }
    else
    {
      k=k+1;
      t=OrderTicket();
      Print("全平函数 :",t);
    }
}
if(k!=0)
{
    for(int i=k-1;i>=0;i--)
    {
   if(OrderSelect(t, SELECT_BY_TICKET)==false)
   {
      Print("平仓错误。。。");
   }
   else
   {
   if(OrderType()==OP_BUY)OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_BID),滑点);
   if(OrderType()==OP_BUYSTOP)OrderDelete(OrderTicket(),CLR_NONE);
   if(OrderType()==OP_BUYLIMIT)OrderDelete(OrderTicket(),CLR_NONE);
   if(OrderType()==OP_SELL) OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_ASK),滑点);
   if(OrderType()==OP_SELLSTOP)OrderDelete(OrderTicket(),CLR_NONE);
   if(OrderType()==OP_SELLLIMIT)OrderDelete(OrderTicket(),CLR_NONE);
   }
    }
}
}   
/////////////////////////////////
void 全部平仓(int 买入平仓滑点,int 卖出平仓滑点)//消灭所有单子
{
         for(int i=0;i<OrdersTotal();i++)
         {
             Print("要全部平仓咯!");
             if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true)
               {
                  if(OrderType()==OP_BUY)                           
                  {
                      if(OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_BID),买入平仓滑点)==false) Print("平买单出错:"+IntegerToString(GetLastError()));
                  }
                  if(OrderType()==OP_SELL)
                  {
                      if(OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_ASK),卖出平仓滑点)==false) Print("平卖单出错:"+IntegerToString(GetLastError()));
                  }
                  
                  if(OrderType()>1)//这句话的意思是if((OrderType()==OP_BUYLIMIT)||(OrderType()==OP_SELLLIMIT)||(OrderType()==OP_BUYSTOP)||(OrderType()==OP_SELLSTOP))
                  {
                      if(OrderDelete(OrderTicket())==false) Print("平挂单出错:"+IntegerToString(GetLastError()));
                  }
               }
         }
}      
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++   

bb2260 发表于 2014-8-31 22:13:07

if(是否持倉()==true)
   {
   printf("當前有倉位");
    //出場();
    全部平倉(500,500);
   }

當然直接平倉

翻开一页 发表于 2014-8-31 22:34:01

有任何问题都没有意见,路过,打打酱油

熙羽 发表于 2014-9-1 13:23:58

如果你只是进行简单控单操作,只要在开单时候加入
if (OrdersTotal() == 0)
{
    Order.....
}

steven-hjzb 发表于 2014-9-1 13:30:59

代码这东西还真的得多多的学习呀!!

翻开一页 发表于 2014-9-1 17:22:59

居然用上了 while(OrdersTotal()!=0),佩服

dbsx 发表于 2014-9-1 19:39:32

翻开一页 发表于 2014-9-1 17:22
居然用上了 while(OrdersTotal()!=0),佩服

循环判断系统中是否还有单,直到系统中单子数量为0才退出。
请问 这句代码有什么问题吗?

dbsx 发表于 2014-9-1 19:41:19

bb2260 发表于 2014-8-31 22:13
if(是否持倉()==true)
   {
   printf("當前有倉位");

可问题是测试刚刚开始什么都没买怎么会有仓呢?就算有 也应该先printf输出一下才对啊。

bb2260 发表于 2014-9-1 23:10:35

dbsx 发表于 2014-9-1 19:41
可问题是测试刚刚开始什么都没买怎么会有仓呢?就算有 也应该先printf输出一下才对啊。
...
你只附部分源碼 沒有人知道是否有先開倉囉

而且看你的輸出 確實是有單子的 否則 怎麼平倉{:soso_e104:}

digit 发表于 2014-9-2 00:01:14

dbsx 发表于 2014-9-1 19:39
循环判断系统中是否还有单,直到系统中单子数量为0才退出。
请问 这句代码有什么问题吗?
...

问题出在:
bool 是否持仓()
{
   if (OrdersTotal()>0) return(true);
   else return(false);
}
可以用下面“到底有多少妹妹()”函数判断单子 比如 if(到底有多少妹妹()>0)...(那么你就干点什么蠢事)
while()语句可以用,但代码不是这样写的 {:soso_e100:}

int 到底有多少妹妹()
{
   int buys=0,sells=0;
   for(int i=0;i<OrdersTotal();i++)
   {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
         if(OrderType()==OP_BUY)buys++;
         if(OrderType()==OP_SELL) sells++;
   }

   if(buys>0) return(buys);
   else       return(-sells);
}





marshal209 发表于 2014-9-2 02:16:29

厉害呀。:victory:

翻开一页 发表于 2014-9-2 09:50:46

本帖最后由 翻开一页 于 2014-9-2 11:31 编辑

其实上面 熙羽 已经点到位了。按你题目上的要求,每次只要求一单,在未平仓之前不再下单,那么代码可以简化。再复杂的要求也是是由这样的简单逻辑演化出来的

if (OrdersTotal() == 0)
{
    ReadyToOrderSend(.....);
}

if(OrdersTotal() > 0)
{

ReadyToClose(....);

}

while(OrdersTotal()!=0)这个语句,你是受了C语言的影响,在MT4这个语句没有太大意义,空套了一层循环。用 if,For和OrderSelect就能解决。如果单数多的话 while增加了程序运行的循环时间,电脑的资源开销增大,如果跑优化测试和复盘,速度减慢

ip0990 发表于 2014-9-2 09:56:32

只开一单lot=1

dbsx 发表于 2014-9-3 07:40:34

bb2260 发表于 2014-9-1 23:10
你只附部分源碼 沒有人知道是否有先開倉囉

而且看你的輸出 確實是有單子的 否則 怎麼平倉


既然你要看全部代码,我贴就是了,只要你不嫌冗余内容太多://+------------------------------------------------------------------+
//|                                                      测试专用2.mq4 |
//|                        Copyright 2014, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2014, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
#property strict
extern   int 移动止损点数=20;

int OnInit()
{
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{

}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+

   void OnTick()
{
   
   if(是否持仓()==true)
   {
   printf("当前有仓位");
   //出场();
    全部平仓(500,500);
   }
else if (是否持仓()==false)
   {
    printf("当前无仓位");
    入场();
   }
}


bool 是否持仓()
{
   if (OrdersTotal()>0)
   {
      //printf("有单子");
      return(true);
   }
   
   else
   //printf("无单子");
   return(false);
}


void 全部平仓(int 买入平仓滑点,int 卖出平仓滑点)//消灭所有单子
{
while(OrdersTotal()!=0)
   {
      printf("要全部平仓咯!");
         for(int i=0;i<OrdersTotal();i++)
         {
             if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true)
               {
                  if(OrderType()==OP_BUY)                           
                  {
                      if(OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_BID),买入平仓滑点)==false) Print("平买单出错:"+IntegerToString(GetLastError()));
                  }
                  if(OrderType()==OP_SELL)
                  {
                      if(OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_ASK),卖出平仓滑点)==false) Print("平卖单出错:"+IntegerToString(GetLastError()));
                  }
                  
                  if(OrderType()>1)//这句话的意思是if((OrderType()==OP_BUYLIMIT)||(OrderType()==OP_SELLLIMIT)||(OrderType()==OP_BUYSTOP)||(OrderType()==OP_SELLSTOP))
                  {
                      if(OrderDelete(OrderTicket())==false) Print("平挂单出错:"+IntegerToString(GetLastError()));
                  }
               }
         }
      }
}   
//+------------------------------------------------------------------+
void 入场()
{
if (OrdersTotal()==0)
{
   if(Open>Open && Close>Close && Open>Close)
   {
   下单(0,0.6,30,30,300,"看涨"+IntegerToString(1),1); //0代表看涨
   }
   else if (Open<Open && Close<Close && Open<Close)
   {
    下单(1,0.7,30,30,300,"看跌"+IntegerToString(2),2); //1代表看空
   }
}   
}
//---------------------------------
void 出场()
{
   for(int i=0;i<OrdersTotal();i++)
   {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
      {
         if(OrderSymbol()==Symbol())
         {
         if(OrderType()<2)//表示持仓的卖单或者买单
          {
         if(OrderType()==OP_BUY)
         {
            printf("买单测试平仓");
            
            if ((Bid - OrderOpenPrice()) > (移动止损点数 * MarketInfo(OrderSymbol(), MODE_POINT)))    //开仓价格 当前止损和当前价格比较判断是否要修改跟踪止赢设置
            {
               printf("买1步");
            if (OrderStopLoss() < Bid - 移动止损点数 * MarketInfo(OrderSymbol(), MODE_POINT))
                {
                  printf("买2步");
               if(OrderModify(OrderTicket(), OrderOpenPrice(),Bid - 移动止损点数 * MarketInfo(OrderSymbol(), MODE_POINT), OrderTakeProfit(),0)==false)
                  {
                   printf("移损设置出错,错误代码:"+IntegerToString(GetLastError()));
                  }
                }
               
             }
             printf("买3步");
            double 移动止损价= Bid - 移动止损点数 * MarketInfo(OrderSymbol(), MODE_POINT);
            int num=iBarShift(OrderSymbol(),0,OrderOpenTime())+2; //定位当前距离开盘中间bar数量+2
            printf("买4步");
            if(Bid < Open || Bid <= 移动止损价)
            {
            printf("买单由于bid"+Bid+"<第一跟k线"+Open+"或者Bid≤移动止损价"+移动止损价+"而平仓");
            全部平仓(500,500);
            }
         }
         
         else if(OrderType()==OP_SELL)
         {
             printf("卖单测试平仓");
            if ((OrderOpenPrice() - Ask) > (移动止损点数 * MarketInfo(OrderSymbol(), MODE_POINT)))    //开仓价格 当前止损和当前价格比较判断是否要修改跟踪止赢设置
            {
            printf("卖1步");
            if ((OrderStopLoss()) > (Ask + 移动止损点数 * MarketInfo(OrderSymbol(), MODE_POINT)))
                {
                printf("卖2步");
               if(OrderModify(OrderTicket(), OrderOpenPrice(),Ask + 移动止损点数 * MarketInfo(OrderSymbol(), MODE_POINT), OrderTakeProfit(),0)==false)
               {
                  printf("移损设置出错,错误代码:"+IntegerToString(GetLastError()));
               }
                }
            }
            printf("卖3步");
            double 移动止损价= Ask + 移动止损点数 * MarketInfo(OrderSymbol(), MODE_POINT);
            int num=iBarShift(OrderSymbol(),0,OrderOpenTime())+2; //定位当前距离开盘中间bar数量+2
            printf("卖4步");
            if(Ask > Open || Ask >= 移动止损价)
            {
            printf("卖单由于Ask"+Ask+">第一跟k线"+Open+"或者Ask≥移动止损价"+移动止损价+"而平仓");
            
            全部平仓(500,500);
            }
         }
          }
          else printf("平挂仓");
         全部平仓(500,500);//如果是挂单的话
         
         }
         else printf("当前图表非目标货币对,请调整!");
      }
   }   
}                     
//-------------------------------------
int 下单(int 看涨或看跌,double Lots,double 止损点数,double 止盈点数, int 滑点,string comment,int magic)//带有止损止盈功能(不用填0)的买入函数
{
   double 止损价位;
   double 止盈价位;
             if(看涨或看跌==0) //0代表看涨
                {   
                   int ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,滑点,0,0,comment,magic,0,White);
                   if(ticket>0) printf("下买单成功,开始止损止盈");
                   else printf("下买单失败,错误代码:"+IntegerToString(GetLastError()));
                  
                   if(OrderSelect(ticket, SELECT_BY_TICKET)==true) //为了保证止损止盈为0时数字设置准确,需进行如下3个判断.
                      {
                      止损价位=NormalizeDouble(OrderOpenPrice()-MarketInfo(OrderSymbol(),MODE_POINT)*止损点数,Digits);
                      止盈价位=NormalizeDouble(OrderOpenPrice()+MarketInfo(OrderSymbol(),MODE_POINT)*止盈点数,Digits);
                     if((止损点数!=0)&&(止盈点数!=0))
                                 {
                                 //printf("止损价位:"+止损价位+"止盈价位:"+止盈价位);
                                 //printf("1:2个都不为0");
                                 if(OrderModify(OrderTicket(),OrderOpenPrice(),止损价位,止盈价位,0,Red)==false)
                                    {
                                    printf("修改错误,代码:"+IntegerToString(GetLastError()));
                                    }
                                    else printf("订单修改成功");
                                 }
                     if((止损点数==0)&&(止盈点数!=0))
                                 {
                                 //printf("2;第1个为0");
                                 
                                    if(OrderModify(OrderTicket(),OrderOpenPrice(),0,止盈价位,0,Red)==false)
                                       {
                                          printf("修改错误,代码:"+IntegerToString(GetLastError()));
                                       }
                                        else printf("订单修改成功");
                                 }
                     if((止损点数!=0)&&(止盈点数==0))
                                 {
                              // printf("3;第2个为0");
                                    if(OrderModify(OrderTicket(),OrderOpenPrice(),止损价位,0,0,Red)==false)
                                       {
                                          printf("修改错误,代码:"+IntegerToString(GetLastError()));
                                       }
                                        else printf("订单修改成功");
                                 }
                     }
                  return(ticket);   
                   }
               else if(看涨或看跌==1) //1代表看空
                  {
                      int ticket=OrderSend(Symbol() ,OP_SELL,Lots,Bid,滑点,0,0,comment,magic,0,Red);
                      if(ticket>0) printf("下卖单成功,开始止损止盈");
                      else printf("下卖单失败,错误代码:"+IntegerToString(GetLastError()));
                     
                      if(OrderSelect(ticket, SELECT_BY_TICKET)==true) //为了保证止损止盈为0时数字设置准确,需进行如下3个判断.
                        {
                              止损价位=NormalizeDouble(OrderOpenPrice()+MarketInfo(OrderSymbol(),MODE_POINT)*止损点数,Digits);
                              止盈价位=NormalizeDouble(OrderOpenPrice()-MarketInfo(OrderSymbol(),MODE_POINT)*止盈点数,Digits);
                               if((止损点数!=0)&&(止盈点数!=0))
                                 {
                              // printf("止损价位:"+止损价位+"止盈价位:"+止盈价位);
                                 //printf("1:2个都不为0");
                                 if(OrderModify(OrderTicket(),OrderOpenPrice(),止损价位,止盈价位,0,Red)==false)
                                    {
                                    printf("修改错误,代码:"+IntegerToString(GetLastError()));
                                    }
                                    else printf("订单修改成功");
                                 }
                               if((止损点数==0)&&(止盈点数!=0))
                                 {
                              // printf("2;第1个为0");
                                 
                                    if(OrderModify(OrderTicket(),OrderOpenPrice(),0,止盈价位,0,Red)==false)
                                       {
                                          printf("修改错误,代码:"+IntegerToString(GetLastError()));
                                       }
                                        else printf("订单修改成功");
                                 }
                              if((止损点数!=0)&&(止盈点数==0))
                                 {
                              // printf("3;第2个为0");
                                    if(OrderModify(OrderTicket(),OrderOpenPrice(),止损价位,0,0,Red)==false)
                                       {
                                          printf("修改错误,代码:"+IntegerToString(GetLastError()));
                                       }
                                        else printf("订单修改成功");
                                 }
                            }
                         return(ticket);
                        }         
            else return(0);         
}


dbsx 发表于 2014-9-3 07:51:46

本帖最后由 dbsx 于 2014-9-3 07:57 编辑

digit 发表于 2014-9-2 00:01
问题出在:

可以用下面“到底有多少妹妹()”函数判断单子 比如 if(到底有多少妹妹()>0)...(那么你就干点 ...
恕我愚钝,我还是不理解,我前贴说的是针对全部平仓()函数,但您这里写的内容是针对判断是否持仓()函数的,另外您说while不能这么用,为什么不能这么用,语法没报错,那就是功能逻辑上有问题咯,那请问是什么问题导致while不能这么用?
您这函数只是随后输出了买单数量和卖单数量,我要达到的功能是只有有单(包括挂单)就平仓,这么写反而觉得麻烦。
页: [1] 2 3
查看完整版本: EA历史测试时为什么会先平仓呢?