I did not analyse all your code, but a quick look shows me that you are not checking for a minimum amount.
The calculation "MathFloor(((Lot/2)/0.01)*0.01)" could result in a value of "0", so you will not be able to close out a volume of "0".
Also, you should be verifying all volume against the brokers conditions of minimum volume, maximum volume and volume step. If you don't verify those metrics you will also get errors when the values are out of those limits.
So, also read the following thread post for an example of how to adjust the volume (lots) accordingly:
Forum on trading, automated trading systems and testing trading strategies
How to calculate lots using multiplier according to number of opened orders?
Fernando Carreiro, 2017.09.01 21:57
Don't use NormalizeDouble(). Here is some guidance (code is untested, just serves as example):
// Variables for Symbol Volume Conditions double dblLotsMinimum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MIN ), dblLotsMaximum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MAX ), dblLotsStep = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP ); // Variables for Geometric Progression double dblGeoRatio = 2.8, dblGeoInit = dblLotsMinimum; // Calculate Next Geometric Element double dblGeoNext = dblGeoInit * pow( dblGeoRatio, intOrderCount + 1 ); // Adjust Volume for allowable conditions double dblLotsNext = fmin( dblLotsMaximum, // Prevent too greater volume fmax( dblLotsMinimum, // Prevent too smaller volume round( dblGeoNext / dblLotsStep ) * dblLotsStep ) ); // Align to Step value
-
double HalfLot = MathFloor(((Lot/2)/0.01)*0.01);
The amount you close must be a multiple of Lot Step. OK, except you shouldn't hard code numbers. - The amount you close must be at least Min Lot. No check as Fernando stated.
- The amount remaining must also be at least Min Lot.
Why did you post your MT4 question in the MT5 EA section instead of the MQL4 section, (bottom of the Root page)?
General rules and best pratices of the Forum. - General - MQL5 programming forum?
Next time post in the correct place. The moderators will likely move this thread there soon.
I did not analyse all your code, but a quick look shows me that you are not checking for a minimum amount.
The calculation "MathFloor(((Lot/2)/0.01)*0.01)" could result in a value of "0", so you will not be able to close out a volume of "0".
Also, you should be verifying all volume against the brokers conditions of minimum volume, maximum volume and volume step. If you don't verify those metrics you will also get errors when the values are out of those limits.
So, also read the following thread post for an example of how to adjust the volume (lots) accordingly:
I change my code as below, but it still doesn't work, I've just saw the thread and I am not sure that I 100% understand it.
I am sorry I sound like I am an absolutely giant dodo (which I probably am) but I think I may need a bit more help...
if(BreakEven==true) { double LotsMinimum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MIN ), LotsMaximum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MAX ), LotsStep = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP ); double HalfLot = MathFloor(((Lot/2)/LotsStep)*LotsStep); HalfLot = fmin( LotsMaximum, fmax( LotsMinimum, round( HalfLot / LotsStep ) * LotsStep ) ); for(int b=OrdersTotal()-1; b>=0; b--) { if(OrderSelect(b,SELECT_BY_POS,MODE_TRADES)) { if(OrderMagicNumber()==MagicNumber) { if(OrderSymbol()==Symbol()) { if(OrderType()==OP_BUY && flagbuy==false) { if(Bid > OrderOpenPrice()+(SL*P)*TPMult) { if(OrderClose(OrderTicket(),HalfLot,Bid,0,clrGainsboro)==true) { flagbuy=true; Print("Order partially closed, Magic number :",MagicNumber); } else Print("Error partially closing order ",GetLastError(),"Magic number",MagicNumber); } } else if(OrderType()==OP_SELL && flagsell==false) { if(Ask < OrderOpenPrice()-(SL*P)*TPMult) { if(OrderClose(OrderTicket(),HalfLot,Ask,0,clrGainsboro)==true) { flagsell=true; Print("Order partially closed, Magic number :",MagicNumber); } else Print("Error partially closing order ",GetLastError(),"Magic number",MagicNumber); } } } } } } }
- The amount you close must be a multiple of Lot Step. OK, except you shouldn't hard code numbers.
- The amount you close must be at least Min Lot. No check as Fernando stated.
- The amount remaining must also be at least Min Lot.
Why did you post your MT4 question in the MT5 EA section instead of the MQL4 section, (bottom of the Root page)?
General rules and best pratices of the Forum. - General - MQL5 programming forum?
Next time post in the correct place. The moderators will likely move this thread there soon.
Sorry about the wrong place for the post...
#1 I've swapped it for lotstep instead of numbers which makes absolutely sense..
#2 & #3 I still think that even after those checks I still would have those error 131 ...
thanks for your help...
Macdrap: I change my code as below, but it still doesn't work, I've just saw the thread and I am not sure that I 100% understand it.
I am sorry I sound like I am an absolutely giant dodo (which I probably am) but I think I may need a bit more help...
Sorry about the wrong place for the post...
#1 I've swapped it for lotstep instead of numbers which makes absolutely sense..
#2 & #3 I still think that even after those checks I still would have those error 131 ...
Like I said, I did not check all your code, only looking at it quickly!
However, in this new version, simplify your calculation, since "my code" is already doing the checking for you!
double LotsMinimum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MIN ), LotsMaximum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MAX ), LotsStep = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP ); double HalfLot = MathFloor( Lot / 2.0 ); HalfLot = fmin( LotsMaximum, fmax( LotsMinimum, round( HalfLot / LotsStep ) * LotsStep ) );
I will check the rest of your code a little be later!
I have taken another look, but you are not assigning the trade's current volume to the variable "Lot". You are just assuming it has a volume of "Lot" based on your calculations.
Plus once the first half of the order is closed, it will not longer have what you think it has, so your calculations will no longer hold. You must first use the OrderLots() function to find out how much volume it has, and only then halve it!
So, once you have selected the order, first use the OrderLots() to get current volume of order, then halve it, and then close it partially.
EDIT: And please, please, use the code styler ([Ctrl+,] or Menu-Tools-Styler) on your code so that it is easier to read and remove all the extra white space that just makes it even more difficult to read.
- docs.mql4.com
I have taken another look, but you are not assigning the trade's current volume to the variable "Lot". You are just assuming it has a volume of "Lot" based on your calculations.
Plus once the first half of the order is closed, it will not longer have what you think it has, so your calculations will no longer hold. You must first use the OrderLots() function to find out how much volume it has, and only then halve it!
So, once you have selected the order, first use the OrderLots() to get current volume of order, then halve it, and then close it partially.
EDIT: And please, please, use the code styler ([Ctrl+,] or Menu-Tools-Styler) on your code so that it is easier to read and remove all the extra white space that just makes it even more difficult to read.
if(BreakEven==true) { double LotsMinimum = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN), LotsMaximum = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX), LotsStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP); double HalfLot = MathFloor(OrderLots()/ 2.0); HalfLot = fmin(LotsMaximum, fmax(LotsMinimum, round(HalfLot / LotsStep) * LotsStep)); for(int b=OrdersTotal()-1; b>=0; b--) { if(OrderSelect(b,SELECT_BY_POS,MODE_TRADES)) { if(OrderMagicNumber()==MagicNumber) { if(OrderSymbol()==Symbol()) { if(OrderType()==OP_BUY && flagbuy==false) { if(Bid > OrderOpenPrice()+(SL*P)*TPMult) { if(OrderClose(OrderTicket(),HalfLot,Bid,0,clrGainsboro)==true) { flagbuy=true; Print("Order partially closed, Magic number :",MagicNumber); } else Print("Error partially closing order ",GetLastError(),"Magic number",MagicNumber); } } else if(OrderType()==OP_SELL && flagsell==false) { if(Ask < OrderOpenPrice()-(SL*P)*TPMult) { if(OrderClose(OrderTicket(),HalfLot,Ask,0,clrGainsboro)==true) { flagsell=true; Print("Order partially closed, Magic number :",MagicNumber); } else Print("Error partially closing order ",GetLastError(),"Magic number",MagicNumber); } } } } } } }
I am sorry to be a pain ... But I don't think I still get it ... now my EA is basically partially closing only the minimum volume (0.01).
I replaced my Lot by the OrderLots() which I suppose is what you meant, I am so sorry but it just feels like the more I think about it the more I get confused about it....
Sorry about the (Ctr+ I normally do it..)
Thank for your time anyway
NO! You can't use OrderLots() outside of a selected order. You did not follow the sequence I explained.
You have to do it for every single order, AFTER you select it and just before you do the partial close.
Here is just a sample summary code to help you understand (code is untested and not compiled, just written out here to show you the idea)...
EDIT: Please note that this is not the best way to do it, but it was a way to show you a possible way to do it!// Function to do have Order Lots outside of OnTick double OrderHalfLots() { double LotsMinimum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MIN ), LotsMaximum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MAX ), LotsStep = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP ); return( fmin( LotsMaximum, fmax( LotsMinimum, round( ( OrderLots() / 2.0 ) / LotsStep ) * LotsStep ) ) ); } void OnTick() { // ... if( OrderClose( OrderTicket(), OrderHalfLots(), Bid, 0, clrGainsboro ) ) { // ... } // ... }
Hi thanks for your great help Fernando,
the only problem with that is that it will even close half of half of the order ...
Then put in a condition to only apply partial closing to orders with a set or expected initial or minimum required volume!
You asked how to close 50%. It has been shown to you. Now take that knowledge and apply it according to the logic you wish to apply to your EAs.
Learning to code properly is not something you learn in a few days. It takes time, effort and dedication.
Also, when closing an order, use OrderClosePrice() instead of Bid or Ask, as it will be the current Market price, valid for both Buy and Sell orders!// Function to calculate Half the Volume double HalfLots( double Lots ) { double LotsMinimum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MIN ), LotsMaximum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MAX ), LotsStep = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP ); return( fmin( LotsMaximum, fmax( LotsMinimum, round( ( Lots * 0.5 ) / LotsStep ) * LotsStep ) ) ); } void OnTick() { // ... double CurrentLots = OrderLots(); if( CurrentLots >= RequiredLots ) { if( OrderClose( OrderTicket(), HalfLots( CurrentLots ), OrderClosePrice(), 0, clrGainsboro ) ) { // ... } } // ... }
- docs.mql4.com
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Hi,
I struggle to partially close an order to 50%, I would like some help please.
I've highlighted in yellow where I think the problem comes from but I can't think of anything else to get arount it.
I keep having this error 131 which is Invalid trade volumes but I can't tell why...
Hope that someone can help me, I saw some other topics but I still can't make it work, it would be brilliant a little bit of help...
Thank you very much.