Hey All,
Can someone please help me with some code to loop through open trades and find the largest open losing trade?
I would really appreciate it.
Thanks.
V
Hey All,
Can someone please help me with some code to loop through open trades and find the largest open losing trade?
I would really appreciate it.
Thanks.
V
Not sure if you want the ticket no of the losing trade or the amount, but this puts both in variables...
It's untested but its pretty closeCode:int i; double LowestProfit=0; int Ticket; for(i=0;i<OrdersTotal();i++){ OrderSelect(i,SELECT_BY_POS); if(OrderType()==OP_SELL || OrderType()==OP_BUY){ if(OrderProfit()<LowestProfit){ LowestProfit=OrderProfit(); Ticket=OrderTicket(); } } }
Paul
Hey Paul,
Thanks for the response. Very close to what I have already, but this returns the entire array of losing trades.
This is for an EA that functions kinda like a grid, where there are multiple winning and losing trades open at any one time. Sorry I should've been more clear in my post.
Here's what I have now:
This loops and prints each trade to the journal, but I need some way to select just the largest negative trade as opposed to all the trades that are less than zero. I'm sure there must be some Math() function that can select just the largest one?Code:void PrintLosers () { int totalorders = OrdersTotal (); double lowest = 0, profit = 0; int ticket; if (totalorders > 0) { RefreshRates (); for (int i = 0; i < totalorders; i++) { OrderSelect (i, SELECT_BY_POS, MODE_TRADES); if ((OrderSymbol()==Symbol()) && (OrderMagicNumber() == InternalMagicNumber)) { if ((OrderType() == OP_BUY) || (OrderType() == OP_SELL)) { profit = OrderProfit(); if (profit < lowest) { lowest = profit; ticket = i; Print("Ticket: ",ticket," || Profit:",lowest); } } } } } return; }
Pulling my hair out.
Thanks for your help
V
Isn't coding fun? I haven't pulled my hair out (yet) but it's gray now.
It looks like all you need to do is move your Print() statement out of the For loop. When the loop finishes your variables "lowest" and "ticket" will have the information you need. Something like this:
Sorry I misunderstood. I have to have things explained to me verrrry clearly!Code:void PrintLosers () { int totalorders = OrdersTotal (); double lowest = 0, profit = 0; int ticket; if (totalorders > 0) { RefreshRates (); for (int i = 0; i < totalorders; i++) { OrderSelect (i, SELECT_BY_POS, MODE_TRADES); if ((OrderSymbol()==Symbol()) && (OrderMagicNumber() == InternalMagicNumber)) { if ((OrderType() == OP_BUY) || (OrderType() == OP_SELL)) { profit = OrderProfit(); if (profit < lowest) { lowest = profit; ticket = i; //Print("Ticket: ",ticket," || Profit:",lowest); } } } } Print("Ticket: ",ticket," || Profit:",lowest); } return; }
Paul
AWESOME!
Paul YOU ARE THE MAN!!!!
I can't believe I was that close to it to start with
Ok to expand on this a little, if I wanted this to close a ratio of profitable to unprofitable trades where would I need to start?
For instance, I'd like the EA to look at all trades, then find say the top 3 profitable trades, and the biggest losing trade, and when those trades combined are equal to the EA's profit dollar input, say 100.00, then close those 4 trades.
Right now the EA opens trades based on an indicator, a modified version of Teddy's Candle Patterns, and based on current trend, and then of course there is drawdown, which I'm trying to reduce through this method.
All trades stay open till they hit profit, or they reach an Equity protection limit as an input, right now I'm playing with 10%.
This little snippet you helped me work out will close out only the biggest losing trade at Equity protection instead of all trades as I had it, should make a big difference.
But ideally, it would be even better if we could look at a ratio of profitable to unprofitable and close those as we go along.
Any additional help would be greatly appreciated.
Thanks so much, it's nice to finally find someone thats willing to lend a hand
V
I think your next step should be to load all open positions in arrays. That makes it much easier to compare values of the various orders. I have a subroutine that does that for you, which I can post if you're interested. The hard part is going to be finding the 3 highest profits and the 3 highest losses (or whatever number you plan to use). The highest and lowest are easy, its the next 2 that will be complicated.
Paul
Great thanks Paul,
I was thinking exactly the same thing, but looking through the docs has left me brain dead, or numbed at the very least.
This little adventure is my first programming gig outside of the PHP world where I'm pretty experienced, but some of this mql4 is confusing the heck out of me.
Appreciate the help.
Hey Paul,
Just wondering what the ETA might be on that subroutine?
Also, does anyone know if it's possible to select a random price point between two given price points?
For instance I want to place a trade at a random price between a 30 pip price range of say .... 1.3268 and 1.3298
I've looked through all the docs and can't seem to find a way to do this.
Thanks.
Here's the subroutine for loading all Orders into arrays:
The way this works is it loads the different values of each order into various arrays, such as BuyOpenPrice[], BuyOpenTicket[], BuyOpenStopLoss[], etc., so the same index in the arrays will be the same order. BuyOpenTicket[1], BuyOpenPrice[1], BuyOpenTakeProfit[1] all refer to the same order. Unfortunately I don't have OrderProfit being captured, so you'll want to add it to the routine, like this:Code:void PopulateOrderArrays(){ int BuyStopCount=0; int BuyOpenCount=0; int SellStopCount=0; int SellOpenCount=0; int BuyLimitCount=0; int SellLimitCount=0; if(ArraySize(BuyStopTicket)>0) ArrayResize(BuyStopTicket,0); if(ArraySize(BuyOpenTicket)>0) ArrayResize(BuyOpenTicket,0); if(ArraySize(SellStopTicket)>0) ArrayResize(SellStopTicket,0); if(ArraySize(SellOpenTicket)>0) ArrayResize(SellOpenTicket,0); if(ArraySize(BuyLimitTicket)>0) ArrayResize(BuyLimitTicket,0); if(ArraySize(SellLimitTicket)>0) ArrayResize(SellLimitTicket,0); int i; int OrderCount=0; string WindowSymbol=Symbol(); for(i=0;i<OrdersTotal();i++){ OrderSelect(i,SELECT_BY_POS); if(OrderMagicNumber()==MagicNo){ OrderCount++; WindowSymbol=OrderSymbol(); switch(OrderType()){ case OP_BUYSTOP: ArrayResize(BuyStopTicket,BuyStopCount+1); BuyStopTicket[BuyStopCount]={OrderTicket()}; ArrayResize(BuyStopPrice,BuyStopCount+1); BuyStopPrice[BuyStopCount]={OrderOpenPrice()}; ArrayResize(BuyStopTakeProfit,BuyStopCount+1); BuyStopTakeProfit[BuyStopCount]={OrderTakeProfit()}; ArrayResize(BuyStopStopLoss,BuyStopCount+1); BuyStopStopLoss[BuyStopCount]={OrderStopLoss()}; ArrayResize(BuyStopLotSize,BuyStopCount+1); BuyStopLotSize[BuyStopCount]={OrderLots()}; BuyStopCount++; break; case OP_BUY: ArrayResize(BuyOpenTicket,BuyOpenCount+1); BuyOpenTicket[BuyOpenCount]={OrderTicket()}; ArrayResize(BuyOpenPrice,BuyOpenCount+1); BuyOpenPrice[BuyOpenCount]={OrderOpenPrice()}; ArrayResize(BuyOpenTakeProfit,BuyOpenCount+1); BuyOpenTakeProfit[BuyOpenCount]={OrderTakeProfit()}; ArrayResize(BuyOpenStopLoss,BuyOpenCount+1); BuyOpenStopLoss[BuyOpenCount]={OrderStopLoss()}; ArrayResize(BuyOpenLotSize,BuyOpenCount+1); BuyOpenLotSize[BuyOpenCount]={OrderLots()}; BuyOpenCount++; break; case OP_SELLSTOP: ArrayResize(SellStopTicket,SellStopCount+1); SellStopTicket[SellStopCount]={OrderTicket()}; ArrayResize(SellStopPrice,SellStopCount+1); SellStopPrice[SellStopCount]={OrderOpenPrice()}; ArrayResize(SellStopTakeProfit,SellStopCount+1); SellStopTakeProfit[SellStopCount]={OrderTakeProfit()}; ArrayResize(SellStopStopLoss,SellStopCount+1); SellStopStopLoss[SellStopCount]={OrderStopLoss()}; ArrayResize(SellStopLotSize,SellStopCount+1); SellStopLotSize[SellStopCount]={OrderLots()}; SellStopCount++; break; case OP_SELL: ArrayResize(SellOpenTicket,SellOpenCount+1); SellOpenTicket[SellOpenCount]={OrderTicket()}; ArrayResize(SellOpenPrice,SellOpenCount+1); SellOpenPrice[SellOpenCount]={OrderOpenPrice()}; ArrayResize(SellOpenTakeProfit,SellOpenCount+1); SellOpenTakeProfit[SellOpenCount]={OrderTakeProfit()}; ArrayResize(SellOpenStopLoss,SellOpenCount+1); SellOpenStopLoss[SellOpenCount]={OrderStopLoss()}; ArrayResize(SellOpenLotSize,SellOpenCount+1); SellOpenLotSize[SellOpenCount]={OrderLots()}; SellOpenCount++; break; case OP_BUYLIMIT: ArrayResize(BuyLimitTicket,BuyLimitCount+1); BuyLimitTicket[BuyLimitCount]={OrderTicket()}; ArrayResize(BuyLimitPrice,BuyLimitCount+1); BuyLimitPrice[BuyLimitCount]={OrderOpenPrice()}; ArrayResize(BuyLimitTakeProfit,BuyLimitCount+1); BuyLimitTakeProfit[BuyLimitCount]={OrderTakeProfit()}; ArrayResize(BuyLimitStopLoss,BuyLimitCount+1); BuyLimitStopLoss[BuyLimitCount]={OrderStopLoss()}; ArrayResize(BuyLimitLotSize,BuyLimitCount+1); BuyLimitLotSize[BuyLimitCount]={OrderLots()}; BuyLimitCount++; break; case OP_SELLLIMIT: ArrayResize(SellLimitTicket,SellLimitCount+1); SellLimitTicket[SellLimitCount]={OrderTicket()}; ArrayResize(SellLimitPrice,SellLimitCount+1); SellLimitPrice[SellLimitCount]={OrderOpenPrice()}; ArrayResize(SellLimitTakeProfit,SellLimitCount+1); SellLimitTakeProfit[SellLimitCount]={OrderTakeProfit()}; ArrayResize(SellLimitStopLoss,SellLimitCount+1); SellLimitStopLoss[SellLimitCount]={OrderStopLoss()}; ArrayResize(SellLimitLotSize,SellLimitCount+1); SellLimitLotSize[SellLimitCount]={OrderLots()}; SellLimitCount++; break; } //switch(OrderType()) } //if(OrderMagicNumber()==MagicNo) } //for(i=0;i<OrdersTotal();i++) return; } //void PopulateOrderArrays()
Of course you'll substitute whatever type ticket you're using for BuyOpen.Code:ArrayResize(BuyOpenProfit,BuyOpenCount+1); BuyOpenProfit[BuyOpenCount]={OrderProfit()};
Make sense?
Now if you want the ticket of the order with the largest profit, you would use:
ArrayMaximum() returns the index of the array with the maximum value, which is why the above line returns the ticket number of the array with the highest profit.Code:int LargestProfitTicket; LargestProfitTicket=BuyOpenTicket[ArrayMaximum(BuyOpenProfit,WHOLE_ARRAY)];
Paul
I"m sure you know you have to use MathRand() to generate a pseudo random number, the problem is it generates a random number between 0 and 32767. Since you want a random number between 0 and 30 you have to use a ratio. Lets say MathRand() generated 22000, so if I remember my math right, you do this: 22000/32767 = x/30. Solve for x to get your number, which is about 20.14. Add the normalized value to your low range number to get the random price. I know it's a lotta steps but I don't know any other way to do it.
Paul