Forex Blog

First-hand Forex trading experience and information about foreign exchange market that will be useful to traders

Archives

RTATC2011 — Day 6 — Position/Order Volume Limits

July 15, 2011 (Last updated on August 7, 2011) by Andriy Moraru

The modification of the EA to make it multi-currency was a tough job and resulted in a heavily modified code of my MT5 expert advisor. Today, I’d like to turn my head to a less complicated yet very important issue — proper position sizing in the ATC EAs.

The Problem

The ATC 2011 rules state:

The minimum trading amount is 0.01 lots, and the maximum is 5 lots, with an increase by 0.01 lot on every order.

The maximum combined amount of positions and pending orders’ lots, regardless of the direction on one symbol, is 15. Stop-losses and take-profits are not taken into account.

This means that it won’t be possible to trade with positions greater than 15 lots. It’s quite bad if one wanted to use an aggressive position sizing strategy and increase orders volume indefinitely. When the EA reaches 15 standard lots limit, the build-up of the balance no longer will be exponential, even for a very profitable strategy. Another issue is that the position bigger than 5 lots need to be opened and closed with more than one order (fortunately, stop-loss and take-profit orders are exempt from this rule). For example, if you wish to open 12 lots long on EUR/USD, you have to send two orders to buy 5 lots each and then one order to buy 2 lots. If you wish to close a position of 12 lots, you have to send two orders to sell 5 lots and then one order to sell 2 lots (of course, you could use 3 equal orders 4 lots each, but that’d be quite an exotic method :)).

The Solution

There are two basic ways to avoid breaking the above-mentioned rules. The first one is to implement your own Buy/Sell procedures for position opening and closing. The second one is to modify the standard MQL library Trade.mqh, which supplies quite powerful PositionOpen() and PositionClose() functions.

I’ve chosen the second way. A coder from MQL5.com forums had shared his version of the modified Trade class for ATC and I’ve modified it to work properly with my EA. The initial version had some errors (it didn’t prevent big orders from sending when no position for the pair was open). If you are anxious to see this modified library, you can scroll down to the Downloads part of this post. The modified lines are marked with “//////////////////////////////” comment.

Results

Obviously, such trading volume limitation has a potential to reduce the performance of the profitable EA. After all, even if there’s enough free margin in the account to open a bigger position, the expert advisor will have to limit the position size with 15 standard lots. If the profit of the previous version of my candidate EA (multi-currency one) was $247,461.84 during the 6-month (2011-01-01-2011-07-01) backtest, the latest version (the one that implements the position sizing limits) showed only $206,618.68 profit for the same period. Nevertheless, it’s still a nice result for me, though it may be too low to achieve anything significant during the Automated Trading Championship this year.

Downloads

The whole package of files required to run this expert advisor can be downloaded for free. It contains the EA file, the custom indicator it uses and the modified Trade library that follows the rules of ATC 2011 position sizing:

You can also download the backtest report of this EA:

In the next issue of the RTATC2011 series, we’ll talk about getting the EA to work in the ATC 2011 trading conditions, with all its requotes, delays, slippages, etc.

You can read the first entry in the RTATC2011 journal to get some basic idea of what’s going on here.

P.S.: 2 months and 9 days left for registration in ATC 2011. 994 participants registered so far. Only 6 participants left to 1,000! Yay!

If you have any questions regarding my position sizing techniques for the upcoming ATC 2011 contest or if you want to suggest a different way to adhere to the maximum volume rules of the championship, please reply using the form below.

8 Responses to “RTATC2011 — Day 6 — Position/Order Volume Limits”

  1. alohafx

    Hi Author! (I don’t know how I call you)
    I’m writing same kind brog like you doing, but sorry in Japanese.
    So I was glad when I find yours, I also have the count down days on the bottom of each entry too!

    And thank you for point out the error in my TradeATC.mqh.
    Also I found we have to adjust the volume before OrderCheck() function.

    -------------------------------------------------------------------------------
    //--- order send >5.0
       if (volume > 15) volume = 15;
       while(volume>5.0)                      ////////////////////////////////
          {                                   ////////////////////////////////
          m_request.volume      =5.0;         ////////////////////////////////
       //--- order check
          if(!OrderCheck(m_request,m_check_result))
            {
             m_result.retcode=m_check_result.retcode;
             if(m_log_level>LOG_LEVEL_NO)
                printf(__FUNCTION__+": %s [%s]",FormatRequest(action,m_request),FormatRequestResult(result,m_request,m_result));
             //--- copy return code
             return(false);
            }
          if(!OrderSend(m_request,m_result))
            {
             if(m_log_level>LOG_LEVEL_NO)
                printf(__FUNCTION__+": %s [%s]",FormatRequest(action,m_request),FormatRequestResult(result,m_request,m_result));
             return(false);
            }
          if(m_log_level>LOG_LEVEL_ERRORS)
             printf(__FUNCTION__+": %s [%s]",FormatRequest(action,m_request),FormatRequestResult(result,m_request,m_result));
          volume      =volume-5.0;           ////////////////////////////////
          }
    -------------------------------------------------------------------------------

    Will you please post about the error on the forum for others?
    Then also I can find your entry name!

    I’m looking forward to see you on the ATC2011!

    Reply

    admin Reply:

    What function is it from?

    Reply

  2. alohafx

    The original Trade.mqh.

    -------------------------------------------------------------------
    bool CTrade::PositionOpen(const string symbol,ENUM_ORDER_TYPE order_type,double volume, double price,double sl,double tp,const string comment)
      {
       //................................
    //--- order check
       if(!OrderCheck(m_request,m_check_result))
         {
          //................................
         }
    //--- order send
       if(!OrderSend(m_request,m_result))
         {
          //................................
         }
       //................................
     }
    -------------------------------------------------------------------

    The first TradeATC.mqh.

    -------------------------------------------------------------------
    bool CTrade::PositionOpen(const string symbol,ENUM_ORDER_TYPE order_type,double volume, double price,double sl,double tp,const string comment)
      {
       //................................
    //--- order check
       if(!OrderCheck(m_request,m_check_result))
         {
          //................................
         }
       while(volume>5.0)                      ////////////////////////////////
          {                                   ////////////////////////////////
    //--- order send
          if(!OrderSend(m_request,m_result))
            {
             //................................
            }
         }
       //................................
     }
    -------------------------------------------------------------------

    The latest one.

    -------------------------------------------------------------------
    bool CTrade::PositionOpen(const string symbol,ENUM_ORDER_TYPE order_type,double volume, double price,double sl,double tp,const string comment)
      {
       //................................
       while(volume>5.0)                      ////////////////////////////////
          {                                   ////////////////////////////////
    //--- order check
          if(!OrderCheck(m_request,m_check_result))
            {
             //................................
            }
    //--- order send
          if(!OrderSend(m_request,m_result))
            {
             //................................
            }
         }
       //................................
     }
    -------------------------------------------------------------------

    And also we need to consider the case when we have 15 lots Buy position,
    we can put maximum 30 lots Sell position.

    Reply

  3. admin

    This should solve that, but it can create a new problem – if a trader just wanted to close his previous position (or a part of it) using an inverse PositionOpen() call, it will mess it up by closing and then opening a new position:

    //--- check position lots max             //////////////////////////////**************
       if(PositionSelect(symbol))
         {
          double vol = PositionGetDouble(POSITION_VOLUME);
          if (((PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) && (order_type == ORDER_TYPE_SELL))
           | ((PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) && (order_type == ORDER_TYPE_BUY)))
             vol = -vol;
          if(vol+volume>15.0)
            {
             volume = 15.0 - PositionGetDouble(POSITION_VOLUME);
             if (volume <= 0)
             {
                m_result.retcode=TRADE_RETCODE_INVALID;
                m_result.comment="Volume excess max";
                return(false);
             }
            }
         }                                    ////////////////////////////****************

    Reply

  4. alohafx

    I don’t understand what you mean the new problem???
    But anyway, I just uploaded the new version as your advise on the forum.
    http://www.mql5.com/en/forum/4020/page1
    Please check it out.

    Reply

    admin Reply:

    Consider that we have 1 lot Long position on EUR/USD. We execute PositionOpen() for Sell of 1 lot. Old version of PositionOpen() would just close the previous Long position (1 lot – 1 lot = 0). New version, will not only close the old position, but will actually open a new Short position of 1 lot (1 lot – 1 lot -1 lot = -1 lot).

    Reply

  5. alohafx

    Since the case above didn’t excess 5 lots neither 15 lots, volume won’t be changed anything. So, new version, old version and even original one will make same result, 1 lot – 1 lot = 0.

    Reply

    admin Reply:

    Oh… Didn’t notice that the condition (vol+volume>15.0) won’t allow that. That’s good :)!

    Reply

Leave a Reply

required
required (will not be published)
optional