赢利时不能加仓的EA,求原因分析

Discussion in 'MetaTrader' started by univetsity, Mar 20, 2011.

  1. 本人新做了EA,但我想要它在赢利时加仓,但不知为何,它总是平掉一个仓位,才能进另外的仓位,不能同时持有两个以上的头寸,请前辈位麻烦看看哪里出了问题。谢谢:D
    代码如下:
    //+------------------------------------------------------------------+
    //| Moving Average.mq4 |
    //| Copyright ?2005, MetaQuotes Software Corp. |
    //| http://www.metaquotes.net/ |
    //+------------------------------------------------------------------+
    #define MAGICMA 20110309

    extern double Lots = 1;
    extern double MaximumRisk = 0.02;
    extern double DecreaseFactor = 3;

    //+------------------------------------------------------------------+
    //| Calculate open positions |
    //+------------------------------------------------------------------+
    int CalculateCurrentOrders(string symbol)
    {
    int buys=0,sells=0;
    //----
    for(int i=0;i<OrdersTotal();i++)
    {
    if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
    if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA)
    {
    if(OrderType()==OP_BUY) buys++;
    if(OrderType()==OP_SELL) sells++;
    }
    }
    //---- return orders volume
    if(buys>0) return(buys);
    else return(sells);
    }
    //+------------------------------------------------------------------+
    //| Calculate optimal lot size |
    //+------------------------------------------------------------------+
    double LotsOptimized()
    {
    double lot=Lots;
    int orders=HistoryTotal(); // history orders total
    int losses=0; // number of losses orders without a break
    //---- select lot size
    lot=NormalizeDouble(AccountFreeMargin()*MaximumRisk/500.0,1);
    Print(MarketInfo(Symbol(), MODE_LOTSIZE));
    Print(MarketInfo(Symbol(), MODE_MINLOT));
    Print(MarketInfo(Symbol(), MODE_LOTSTEP));
    Print(MarketInfo(Symbol(), MODE_MAXLOT));

    //---- calculate number of losses orders without a break
    if(DecreaseFactor>0)
    {
    for(int i=orders-1;i>=0;i--)
    {
    if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false) { Print("Error in history!"); break; }
    if(OrderSymbol()!=Symbol() || OrderType()>OP_SELL) continue;
    //----
    if(OrderProfit()>0) break;
    if(OrderProfit()<0) losses++;
    }
    if(losses>1) lot=NormalizeDouble(lot-lot*losses/DecreaseFactor,1);
    //this is an smart technical design,but losses stands lossing profit,not money may cause problems.
    //modify them follow as:accountfreemargin()-orderprofit()
    }
    //---- return lot size
    if(lot<1) lot=1;
    return(lot);
    }
    //+------------------------------------------------------------------+
    //| Check for open order conditions |
    //+------------------------------------------------------------------+
    void CheckForOpen()
    {
    double m1,m3,m4,ticket1,ticket2;
    int res;
    //---- go trading only for first tiks of new bar
    if(Volume[0]>1) return;
    //---- get Moving Average
    m1=iMA(NULL,0,55,0,MODE_SMA,PRICE_CLOSE,0);

    m3=iMA(NULL,0,55,0,MODE_SMA,PRICE_CLOSE,3);
    m4=iMA(NULL,0,55,0,MODE_SMA,PRICE_CLOSE,5);
    //---- sell conditions
    if (m1<m3-0.0003)
    {ticket1=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,5,Ask+105*Point,0,"SELL#1",MAGICMA,0,Red); return; }
    if (m1<m4-0.0004)
    {ticket2=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,5,Ask+105*Point,0,"SELL#2",MAGICMA,0,Green); return; }

    //---- buy conditions
    if ( m1>m3+0.0003)
    { ticket1=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,5,Bid-105*Point,0,"BUY#1",MAGICMA,0,Blue); return; }
    if (m1>m4+0.0004)
    { ticket2=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,5,Bid-105*Point,0,"BUY#2",MAGICMA,0,Yellow); return;}


    //----
    }
    //+------------------------------------------------------------------+
    //| Check for close order conditions |
    //+------------------------------------------------------------------+
    void CheckForClose()
    {
    double m1,m3,m4;
    //---- go trading only for first tiks of new bar
    if(Volume[0]>1) return;
    //---- get Moving Average
    m1=iMA(NULL,0,55,0,MODE_SMA,PRICE_CLOSE,0);

    m3=iMA(NULL,0,55,0,MODE_SMA,PRICE_CLOSE,3);
    m4=iMA(NULL,0,55,0,MODE_SMA,PRICE_CLOSE,5);
    //----
    for(int i=0;i<OrdersTotal();i++)
    {
    if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
    if(OrderMagicNumber()!=MAGICMA || OrderSymbol()!=Symbol()) continue;
    //---- check order type
    if(OrderType()==OP_BUY)
    {
    if(m1<m3-0.0002)
    {OrderClose(OrderTicket(),OrderLots(),Bid,3,Orange); break; }
    if(m1<m4-0.0003)
    { OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); break; }
    }
    if(OrderType()==OP_SELL)
    {
    if(m1>m3+0.0002)
    {OrderClose(OrderTicket(),OrderLots(),Ask,3,Tan); break; }
    if(m1>m4+0.0003)
    {OrderClose(OrderTicket(),OrderLots(),Ask,3,White); break; }
    }
    }
    //----
    }
    //+------------------------------------------------------------------+
    //| Start function |
    //+------------------------------------------------------------------+
    void start()
    {
    //---- check for history and trading
    if(Bars<55 || IsTradeAllowed()==false) return;
    //---- calculate open orders by current symbol
    if(CalculateCurrentOrders(Symbol())==0) CheckForOpen();
    else CheckForClose();
    //----
    }
    //+------------------------------------------------------------------+
     
  2. if(CalculateCurrentOrders(Symbol())==0) CheckForOpen();
    这句有问题吧,如果没仓位才执行CheckForOpen()??
     
  3. 想想确实是这句有问题 但不知如何修改 第二个单尽管是独立的,但开仓时,第一单肯定会赢利的 但不太明白如果表达。前辈再明示一下,谢谢:p
     
  4. CheckForOpen()和CheckForClose()并排执行。CheckForOpen()内部计算要加仓的数量及是否盈利。

    CheckForOpen()
    CheckForClose()


    这是我EA的加仓语句,在checkforopen里,做个例子。

    if( AddPositionSignal == 1) //加仓信号
    {
    if(BuyOrderCount > 0 && BuyOrderCount <= AddPositionCount && Ask > LastOrderOpenPrice + AddPositionPips * myPoint)
    //有多头仓位,及多头仓位数不超过加仓的次数AddPositionCount ,如只能加仓2次。现价大于上次开仓价格LastOrderOpenPrice 多少点数后才执行加仓。
    {
    Lot = OptimalLots(Symbol(), PerTradePercent,StopLoss);
    if(Lot + OrdersBuyLots > MaxTradeLots)
    Lot = NormalizeDouble(MaxLotsTotal - OrdersSellLots,LotsDecimal);
    if(Lot < MarketInfo(Symbol(),MODE_MINLOT))
    {
    Print("Lots > MaxTradeLots");
    return(0);
    }

    tiket = OpenPosition(OP_BUY,Symbol(), Lot,ST(),TP(), UserComment+ "SUB", Magic);
     
  5. nix

    nix

    if(CalculateCurrentOrders(Symbol())==0) CheckForOpen();
    else CheckForClose();

    这不明摆着么?如果没有单子,才检查信号,如果,有单子,才去检查关单条件

    朋友还是先看看手册把基本的编程结构控制看一下吧
     
  6.  
  7. nix

    nix

    啥前辈,亏钱时间久点而已,你贴的代码少。。。ER。。。。暂时看不出啥门道
     
  8. 这个条件有问题if(Ask>OrderOpenPrice()+300*Point)

    你执行开仓语句时,有没有循环执行orderselect语句,如果没有,那么你的orderopenprice()就不是一个体现出真正开仓价的数值,所以才会重复执行(错误的openprice)。

    仓位的最后开盘价,需要提前得到,才能在上面的语句中使用。
     
  9. nix

    nix

    原来一楼貌似是完整的代码?。。。半夜上网老眼昏花,看来我是老了,坐在电脑前面太多了

    不过如果你把一楼的改过了,那又是另外一回事了。

    看来你只是自己编程编乱套了,自己慢慢理清嘛,建议能PRINT的地方都PRINT一下数值,来DEBUG
    或者 能COMMENT到界面显示也COMMENT一下,然后用VISUAL MODE 认真检查
     
  10. 我写了如下代码:
    void CheckForOpen()
    {
    double m1,m3,a,ticket1,ticket2,b;
    int res;
    if(Volume[0]>1) return;
    a=iADX(NULL,0,55,4,MODE_MAIN,0);
    m1=iMA(NULL,0,144,0,MODE_SMA,PRICE_CLOSE,0);
    m3=iMA(NULL,0,144,0,MODE_SMA,PRICE_CLOSE,1);
    if (a>15)
    {
    //---- sell conditions
    if (m1<m3-0.00005)
    { ticket1=OrderSend(Symbol(),OP_SELL,1,Bid,5,Ask+1050*Point,0,"SELL#1",MAGICMA,0,Red);return;}


    //---- buy conditions
    if ( m1>m3+0.00005)
    { ticket1=OrderSend(Symbol(),OP_BUY,1,Ask,5,Bid-1050*Point,0,"BUY#1",MAGICMA,0,Blue);return; }
    add();
    }

    }


    void add()
    {
    bool res = false;
    int total = OrdersTotal(),ticket2;
    for(int i=0; i<OrdersTotal(); i++)
    {
    if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) &&
    OrderMagicNumber()==MAGICMA && OrderSymbol()==Symbol())
    {
    if(OrderType()==OP_BUY)
    {
    if(OrderProfit()>300*Point)//Ask>OrderOpenPrice()+300*Point
    {
    ticket2=OrderSend(Symbol(),OP_BUY,1,Ask,5,Bid-1050*Point,0,"BUY#2",MAGICMA,0,Yellow);// return;
    }
    }
    if(OrderType()==OP_SELL)
    {
    if(OrderProfit()>300*Point)//Bid<OrderOpenPrice()-300*Point
    {
    ticket2=OrderSend(Symbol(),OP_SELL,1,Bid,5,Ask+1050*Point,0,"SELL#2",MAGICMA,0,White);//return;
    }
    }
    }
    }
    }
    发现第一开仓条件(m1<m3-0.00005)在CalculateCurrentOrders(Symbol())<2(我用这个控制总仓位数)下仍然执行两次,而add()不能在正确价位执行,而且关仓也不符合我的关仓条件。帮忙再看看 新手问题一大堆:confused:
     
  11. 看不太懂。

    CalculateCurrentOrders(Symbol())<2本来就是可以执行两次,0和1都执行,这个正确。

    OrderProfit()的单位是美元吧(美分帐户另当别论), 300*Point这个却是点数,两者的单位并不一致.
     
  12. 是哪里看不懂呢?我是把加仓单独做一个函数,然后放到开仓函数里运行的
    我是想使第一进场条件只执行一行,然后加仓条件如果达到的话,加仓一次。但在CalculateCurrentOrders(Symbol())<2 第一进场条件经常连续运行2次,加仓的却偶尔会反复开仓关仓 但多数时候不执行。
    另外一个问题是后来加了TS()也只能在平掉一仓后才能开始起作用,而不能只要符合条件就起作用。这两个问题可能根源都在开仓函数的控制上出了问题。但我始终没找到解决办法,很是郁闷!:(
    那个orderprofit()的条件 我发现与Bid<OrderOpenPrice()-300*Point
    在运行时会得到同样的结果。这个也不太明白原因。
     
  13. nix

    nix

    又看了一眼你的程序

    最好把所有处理订单模块化,这样你写起来检查起来思路都会很清晰,貌似官网也有处理订单的LIB?
    我一般都会有CHECKORDERS,
    CHECK OPEN BUY
    CLOSE ALL BUY
    BREAKEVEN ALL BUY
    等函数,而且我所有其他EA要使用的时候都可以直接COPY PASTE, 函数一般只有一个参数
    那就是MAGICNO,开单的函数,会多2两个参数,STOPLOSS TAKEPROFIT(因为SLIPPAGE那些一般设全局变量)。写EA一定要用上MAGICNO,不然以后要是跑多EA你就麻烦了,或者跟手动单混在一起。

    如果你的程序全,有空我帮你看看,,,最近太忙
     
  14. 谢谢前辈提醒。帮忙看看下面的代码:
    if(DecreaseFactor>0)
    {
    for(int i=orders-1;i>=0;i--)
    {
    if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false) { Print("Error in history!"); break; }
    if(OrderSymbol()!=Symbol() || OrderType()>OP_SELL) continue;
    if(OrderProfit()>0) break;
    if(OrderProfit()<0) losses++;
    }
    if(losses>=1) lot=NormalizeDouble(lot-lot*losses/DecreaseFactor,2);
    for(int j=0;j<orders;j++)
    {
    if(OrderSelect(j,SELECT_BY_POS,MODE_HISTORY)==false) { Print("Error in history!"); break; }
    if(OrderSymbol()!=Symbol() || OrderType()>OP_SELL) continue;
    if(OrderProfit()<0) break;
    if(OrderProfit()>0) wins++;
    }
    if(wins>=5) lot=NormalizeDouble(lot-lot*(wins-5)/DecreaseFactor,2);
    }

    我是想这段代码控制 仓位 上面一半是亏损是减仓,下面的一半是连盈5单后减仓,但现在只有亏损减仓起作用,连盈减仓的不起作用。前辈帮忙看看是什么问题 一个函数里用这样两个循环应该没问题吧。:)
     
  15. nix

    nix

    没必要算两次了吧,第一次判断亏损的时候 ELSE一下不就是盈利的了?
     
  16. nix

    nix

    for(int i=orders-1;i>=0;i--)
    {
    if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false) { Print("Error in history!"); break; }
    if(OrderSymbol()!=Symbol() || OrderType()>OP_SELL) continue;
    if(OrderProfit()>=0) {
    wins++;
    } else {
    losses++;
    }
    }

    if(losses>=1) lot=NormalizeDouble(lot-lot*losses/DecreaseFactor,2);
    if(wins>=5) lot=NormalizeDouble(lot-lot*(wins-5)/DecreaseFactor,2);

    这样不就有效率点?

    问题可能出现在你select 的方式 i j变量一个从大变到小,一个从小变到大
     
  17. 当成交单子的历史多了,肯定存在又符合第一种情况(亏损)又同时符合第二种情况(连赢)的情况,所以无法区分到底是亏损呢还是连赢呢,或者是选计算亏损,然后在亏损的结果上再计算连赢??

    另外,你代码计算连赢的方法也不对(仅是计算所有赢利的单子数量,并不存在连续的概念)
     
  18. nix

    nix

    haha 还真是,一般这种情况我都不会去看订单这么麻烦,自己做个数组来存储安心多了

    直接COMMENT到CHART上来调试
     
  19. 我的代码是计算连盈的 确实是select的计算顺序有问题,目前已解决。
    上次前辈说看不懂我贴出来的加仓代码,不太明白哪里看不懂。目前代码起作用,但只能算有效加仓一次。我不确定是不是
    Ask>OrderOpenPrice()+300*Point 这一句有问题,这里的orderopenprice()只是第一进场单的,而不是前辈所说的“上一次开仓价” 不懂如何获取“上一次开仓价”,应该不会用select再从加仓单里来一遍吧。

    另外还有两个低级的问题:1,如何获取大量的历史K线数据,目前我只找到半年的 更早的似乎历史数据库里也没有,有什么渠道更获取更全的数据呢? 2,我现在用不同IB的平台测试同一EA,同样标的,时段,保证金,居然得到完全不一样的结果,成交单子价格、时点不同。这个不知是何原因 3,复盘模型 有3个选项, 如果实盘,那是默认的哪个模型。不同模型对测试结果有何不同影响。 我自己也不断找相关资料,前辈指点一下就更好了。:D