LotSize based on Centroid [SOLVED]

 

As you know I recently started with mq5, and it's been an exciting challenge for me, but I run into some problems along the way.

This one in particular has me thinking about it for several hours. It is about calculating the size of an operation based on the centroid.

The error is that the LotSize is always fixed and does not vary


double Lot_Size_B(ENUM_ORDER_TYPE type)
  {
   double tradeCenter = TradesCenterPrice(type);
   if(0 == tradeCenter)
      return NormalizeDouble(Initial_Lot, LotDigits);
   int totalTradesAbove = TradesAbovePrice_Counter(type, tradeCenter);
   int totalTradesBelow = TradesBelowPrice_Counter(type, tradeCenter);
   double price = (type == ORDER_TYPE_BUY) ? getAsk() : getBid();
   double lots = (price > tradeCenter) ? MathPow(MM_Martingale_ProfitFactor, totalTradesAbove) * Initial_Lot : (price < tradeCenter) ? MathPow(MM_Martingale_LossFactor, totalTradesBelow) * Initial_Lot : Initial_Lot;
   return NormalizeDouble(lots, LotDigits);
  }
                                                         |
//+------------------------------------------------------------------+
double TradesCenterPrice(ENUM_ORDER_TYPE type)
  {
   double center = 0;
   int count = 0;
   for(int i = 0; i < PositionsTotal(); i++)
     {
      if(Position.SelectByIndex(i) && Position.Type() == type)
        {
         center += Position.PriceOpen();
         count++;
        }
     }
   if(count == 0)
      return 0;
   return center / count;
  }

//+------------------------------------------------------------------+
int TradesAbovePrice_Counter(ENUM_ORDER_TYPE type, double price)
  {
   int count = 0;
   for(int i = 0; i < PositionsTotal(); i++)
     {
      if(Position.SelectByIndex(i) && Position.Type() == type && Position.PriceOpen() > price)
        {
         count++;
        }
     }
   return count;
  }


//+------------------------------------------------------------------+
int TradesBelowPrice_Counter(ENUM_ORDER_TYPE type, double price)
  {
   int count = 0;
   for(int i = 0; i < PositionsTotal(); i++)
     {
      if(Position.SelectByIndex(i) && Position.Type() == type && Position.PriceOpen() < price)
        {
         count++;
        }
     }
   return count;
  }
 

I know what a centroid is, but I don't see how you are applying the concept here. Can you explain in more detail?

Also, that very long line may need to be styled a little to make it more readable. Maybe something like this?

double lots =
   price > tradeCenter
      ? MathPow( MM_Martingale_ProfitFactor, totalTradesAbove) * Initial_Lot 
      : ( price < tradeCenter
             ? MathPow( MM_Martingale_LossFactor, totalTradesBelow) * Initial_Lot
             : Initial_Lot );

Is the above logic correct?

Another thing to consider, is that when calculating the net open price of a basket of positions, you also need to consider their volume, not just their price, as follows:

 
Fernando Carreiro #:

I know what a centroid is, but I don't see how you are applying the concept here. Can you explain in more detail?

Also, that very long line may need to be styled a little to make it more readable. Maybe something like this?

Is the above logic correct?

Another thing to consider, is that when calculating the net open price of a basket of positions, you also need to consider their volume, not just their price, as follows:


Yeah, maybe I shouldn't have used the word "centroid", since I'm not taking volume into account here.  It is a simplified version that takes into account the average price
 
Enrique Enguix #: Yeah, maybe I shouldn't have used the word "centroid", since I'm not taking volume into account here.  It is a simplified version that takes into account the average price
Whether it is "centroid" or not, to get average price, you need to consider the volume every-time anyway. Or else your volume for the new resulting order is not going to balance out.
 
Fernando Carreiro #:
Whether it is "centroid" or not, to get average price, you need to consider the volume every-time anyway. Or else your volume for the new resulting order is not going to balance out.

What I want to do is much simpler than that. I want an average to be made only and exclusively of the average price between the open trades of the same type, for that I have created "double TradesCenterPrice(int type)". And then I have created two more functions, one that counts how many trades are above the average price "TradesAbovePrice_Counter" and one that counts how many are below "TradesBelowPrice_Counter".


I do this to determine the size of trades to be opened next. I extract these functions in a comment, both for BUY and SELL, and in general, those associated with SELL are not showing the average price or the number of operations above and below that there are

 
Enrique Enguix #:

What I want to do is much simpler than that. I want an average to be made only and exclusively of the average price between the open trades of the same type, for that I have created "double TradesCenterPrice(int type)". And then I have created two more functions, one that counts how many trades are above the average price "TradesAbovePrice_Counter" and one that counts how many are below "TradesBelowPrice_Counter".


I do this to determine the size of trades to be opened next. I extract these functions in a comment, both for BUY and SELL, and in general, those associated with SELL are not showing the average price or the number of operations above and below that there are

I'd say this indicates an enum issue 

They have same values however 

[0] enum ENUM_POSITION_TYPE > POSITION_TYPE_BUY
[0] enum ENUM_ORDER_TYPE > ORDER_TYPE_BUY
[0] enum ENUM_DEAL_TYPE > DEAL_TYPE_BUY
[1] enum ENUM_POSITION_TYPE > POSITION_TYPE_SELL
[1] enum ENUM_ORDER_TYPE > ORDER_TYPE_SELL
[1] enum ENUM_DEAL_TYPE > DEAL_TYPE_SELL

Are you sending a ORDER_TYPE_SELL_LIMIT or something instead of sell ?

 
Lorentzos Roussos #:

I'd say this indicates an enum issue 

They have same values however 

Are you sending a ORDER_TYPE_SELL_LIMIT or something instead of sell ?

No, only ORDER_TYPE_SELL. 
It is the same code for BUY and SELL, however the data is not displayed correctly.  Even sells are counted as buys
 
Enrique Enguix #:
No, only ORDER_TYPE_SELL. 
It is the same code for BUY and SELL, however the data is not displayed correctly.  Even sells are counted as buys

what does the .TypeDescription() return for the positions ? 

https://www.mql5.com/en/docs/standardlibrary/tradeclasses/cpositioninfo/cpositioninfotypedescription

Documentation on MQL5: Standard Library / Trade Classes / CPositionInfo / TypeDescription
Documentation on MQL5: Standard Library / Trade Classes / CPositionInfo / TypeDescription
  • www.mql5.com
TypeDescription - CPositionInfo - Trade Classes - Standard Library - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 

Hi mate,

I had a quick look in the code you've posted, and at a glance nothing stand out.

Since you only posted a particular part of your code,

It could be that the problem is elsewhere.

For example- maybe the 'Lot_Size_B' function doesn't even get called, and the fixed lot is a result of a logical bug elsewhere in your code.


I would either start with running it in debugger with breakpoints,

Or adding Print() after each line, and print the data of each variable (tradeCenter, totalTradesAbove, totalTradesBelow, etc'), to better pin down where your problem lays.


Try adding a Print commands to print the variable values and post it here.

It will help us help you.

 

I think in this case a picture will be better than a thousand words. You can see how in the graph there are several sell operations, but the sell comments are not even filled





void OnTick()
  {

  Comment ("Center Price Buys:   ",TradesCenterPrice (ORDER_TYPE_BUY),
         "\nCenter Price Sells:  ",TradesCenterPrice (ORDER_TYPE_SELL),
         "\nTrades Above Price Buys:  ",TradesAbovePrice_Counter(ORDER_TYPE_BUY,TradesCenterPrice (ORDER_TYPE_BUY)) ,  
         "\nTrades Above Price Sells: ",TradesAbovePrice_Counter(ORDER_TYPE_SELL,TradesCenterPrice (ORDER_TYPE_SELL)) ,  
         "\nTrades Below Price Buys:  ",TradesBelowPrice_Counter(ORDER_TYPE_BUY,TradesCenterPrice (ORDER_TYPE_BUY)) ,  
         "\nTrades Below Price Sells: ",TradesBelowPrice_Counter(ORDER_TYPE_SELL,TradesCenterPrice (ORDER_TYPE_SELL)));   


//All rest code



}


I have assumed that I am not and will not be a great mq5 programmer, but every step I take I find myself with two stones in the road

 
Lorentzos Roussos #:

what does the .TypeDescription() return for the positions ? 

https://www.mql5.com/en/docs/standardlibrary/tradeclasses/cpositioninfo/cpositioninfotypedescription

Sorry mate, I didn't see this message.  I'll check.  Thanks