How to use previous stop loss?

 

Hi All,


I have been trying to get my EA to place an order with the same previous stop loss size (it is based on a candle low/high) for hours now with no luck.

Basically, I would have to store and use the last stop loss value and call it for the order below. Please note the order below is seperate from the initial order placed but needs the same stop loss.


void BuyOrderRisk2()
{
    double takeprofit = 0;
    double stoploss = 0;
    double profit = 0;
    datetime lastCloseTime = 0;
    int cnt = OrdersHistoryTotal();
    for (int i=0; i < cnt; i++)
    {
        if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue;
        if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && lastCloseTime < OrderCloseTime())
        {
            lastCloseTime = OrderCloseTime();
            profit = OrderProfit();
            stoploss = OrderStopLoss();
            takeprofit = OrderTakeProfit(); //this is where I am trying to call the previous trades stop loss and take profit, but when I run the EA I get order modify errors, please help!
        }
    }
    if (ProfitHistoryOrdersCount(RecoveryTrades)) 
    {
        if (RiskResetOnProfit)
        CurrentRisk = RiskPercent;
    }
    else if (profit < 0)
    {
        CurrentRisk = CurrentRisk * RiskMpOnLoss;
    }
    if (CurrentRisk > MaxRisk)
    {
        CurrentRisk = MaxRisk;
    }
     if (profit > 0)
    {
        CurrentRisk = RiskPercent;
    }
    double lotsize = MarketInfo(Symbol(),MODE_LOTSIZE) / 1;
    double pipsize = 100 * 10;
    double maxlots = AccountEquity() / 100 * CurrentRisk / lotsize * pipsize;
    if (StopLoss == 0) Print("OrderSend() error - stoploss can not be zero");
    double lots = maxlots / StopLoss * 10;
    
    // calculate lot size based on current risk
    double lotvalue = 0.001;
    double minilot = MarketInfo(Symbol(), MODE_MINLOT);
    int powerscount = 0;
    while (minilot < 1)
    {
        minilot = minilot * MathPow(10, powerscount);
        powerscount++;
    }
    lotvalue = NormalizeDouble(lots, powerscount - 1);
    
    if (lotvalue < MarketInfo(Symbol(), MODE_MINLOT))    // make sure lot is not smaller than allowed value
    {
        lotvalue = MarketInfo(Symbol(), MODE_MINLOT);
    }
    if (lotvalue > MarketInfo(Symbol(), MODE_MAXLOT))    // make sure lot is not greater than allowed value
    {
        lotvalue = MarketInfo(Symbol(), MODE_MAXLOT);
    }

    
    int ticket = -1;
    if (true)
    ticket = OrderSend(Symbol(), OP_BUY, lotvalue, Ask, Slippage, 0, 0, ExpertName, MagicNumber, 0, Blue);
    else
    ticket = OrderSend(Symbol(), OP_BUY, lotvalue, Ask, Slippage, stoploss, takeprofit, ExpertName, MagicNumber, 0, Blue);
    if (ticket > -1)
    {
        if (true)
        {
            OrderSelect(ticket, SELECT_BY_TICKET);
            bool ret = OrderModify(OrderTicket(), OrderOpenPrice(), stoploss, takeprofit, 0, Blue);
            if (ret == false)
            Print("OrderModify() error - ", ErrorDescription(GetLastError()));
        }
            
    }
    else
    {
        Print("OrderSend() error - ", ErrorDescription(GetLastError()));
    }
}

 

I think you are misunderstanding how if works . . .

int ticket = -1;   //  this has no bearing on the following   if  

if (true)                                                                                                    // true is always true
   ticket = OrderSend(Symbol(), OP_BUY, lotvalue, Ask, Slippage, 0, 0, ExpertName, MagicNumber, 0, Blue);    // so this line is always executed

else
   ticket = OrderSend(Symbol(), OP_BUY, lotvalue, Ask, Slippage, stoploss, takeprofit, ExpertName, MagicNumber, 0, Blue); // true is always true so this is never executed

You might want to check that the order you are taking the stoploss and takeprofit from is actually a OP_BUY . . . and that the TP and SL isn't too close to the current Ask price.

What error do you get from the OrderModify ?

 

Just had a brief glimpse at your code.

//this is where I am trying to call the previous trades stop loss and take profit, but when I run the EA I get order modify errors, please help!

The order modify error is most likely from where you use OrderModify()

bool ret = OrderModify(OrderTicket(), OrderOpenPrice(), stoploss, takeprofit, 0, Blue);

... not from where you are using OrderSelect() to get the order sl.

It looks like you are selecting the position by cycling through your ENTIRE trade history. Remember that the history is indexed forwards, so the earliest trade in your trade history is number 0.

(Also remember that the trade history is determined by the time period you select in metatrader, and the history backdata saved by your broker, so it may not show all the trades you ever placed on that account.)

Rather than cycling from the past to the present, you could save time by cycling from the present to the past.

Even better, if it suits your system, you could keep a separate note of the sl you require as a separate double variable, and only update it when required. That way you would avoid the hassle and time of checking previous orders, and could query that variable directly.

Either way, make sure you are not trying to set a sl or tp on the wrong sides of your open price. It does not seem as though you are checking this with the code before placing the order, though I could be wrong.

Remember that the sl and tp are the "full" price values, not the number of pips for offset from those values.

 

I am getting order modify errors 130 and invalid stops.

First I place a buy order as below which executes just fine:

void BuyOrderRisk()
{
    double profit = 0;
    datetime lastCloseTime = 0;
    int cnt = OrdersHistoryTotal();
    for (int i=0; i < cnt; i++)
    {
        if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue;
        if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && lastCloseTime < OrderCloseTime())
        {
            lastCloseTime = OrderCloseTime();
            profit = OrderProfit();
        }
    }
    if (ProfitHistoryOrdersCount(RecoveryTrades)) 
    {
        if (RiskResetOnProfit)
        CurrentRisk = RiskPercent;
    }
    else if (profit < 0)
    {
        CurrentRisk = CurrentRisk * RiskMpOnLoss;
    }
    if (CurrentRisk > MaxRisk)
    {
        CurrentRisk = MaxRisk;
    }
     if (profit > 0)
    {
        CurrentRisk = RiskPercent;
    }
    double lotsize = MarketInfo(Symbol(),MODE_LOTSIZE) / 1;
    double pipsize = 100 * 10;
    double maxlots = AccountEquity() / 100 * CurrentRisk / lotsize * pipsize;
    if (StopLoss == 0) Print("OrderSend() error - stoploss can not be zero");
    double lots = maxlots / StopLoss * 10;
    
    // calculate lot size based on current risk
    double lotvalue = 0.001;
    double minilot = MarketInfo(Symbol(), MODE_MINLOT);
    int powerscount = 0;
    while (minilot < 1)
    {
        minilot = minilot * MathPow(10, powerscount);
        powerscount++;
    }
    lotvalue = NormalizeDouble(lots, powerscount - 1);
    
    if (lotvalue < MarketInfo(Symbol(), MODE_MINLOT))    // make sure lot is not smaller than allowed value
    {
        lotvalue = MarketInfo(Symbol(), MODE_MINLOT);
    }
    if (lotvalue > MarketInfo(Symbol(), MODE_MAXLOT))    // make sure lot is not greater than allowed value
    {
        lotvalue = MarketInfo(Symbol(), MODE_MAXLOT);
    }
    double SL = Low[0]- StopLoss*PipValue*Point;
    if (StopLoss == 0) SL = 0;
    double TP = High[1] + TakeProfit*PipValue*Point;
    if (TakeProfit == 0) TP = 0;
    int ticket = -1;
    if (true)
    ticket = OrderSend(Symbol(), OP_BUY, lotvalue, Ask, Slippage, 0, 0, ExpertName, MagicNumber, 0, Blue);
    else
    ticket = OrderSend(Symbol(), OP_BUY, lotvalue, Ask, Slippage, SL, TP, ExpertName, MagicNumber, 0, Blue);
    if (ticket > -1)
   
    {
        if (true)
        {
            OrderSelect(ticket, SELECT_BY_TICKET);
            bool ret = OrderModify(OrderTicket(), OrderOpenPrice(), SL, TP, 0, Blue);
            if (ret == false)
            Print("OrderModify() error - ", ErrorDescription(GetLastError()));
        }
            
    }
    else
    {
        Print("OrderSend() error - ", ErrorDescription(GetLastError()));
    }
}


If that buy order is a loss then the EA will trigger a sell order. Its more or less a carbon copy of the buy order BUT, it needs to use the same stop loss/ take profit distance (not price level) as the buy order. As you can see above, the buy order uses the previous high/low for the SLP and TP. Below is the sell order that I need to modify:

void SellOrderRisk2()
{
    double takeprofit = 0;
    double stoploss = 0;    
    double profit = 0;
    datetime lastCloseTime = 0;
    int cnt = OrdersHistoryTotal();
    for (int i=0; i < cnt; i++)
    {
        if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue;
        if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && lastCloseTime < OrderCloseTime())
        {
            lastCloseTime = OrderCloseTime();
            profit = OrderProfit();
            stoploss = OrderStopLoss();
            takeprofit = OrderTakeProfit(); //this is where I am trying to call the previous trades stop loss and take profit, but when I run the EA I get order modify errors, please help!
        }
    }
    if (ProfitHistoryOrdersCount(RecoveryTrades)) 
    {
        if (RiskResetOnProfit)
        CurrentRisk = RiskPercent;
    }
    else if (profit < 0)
    {
        CurrentRisk = CurrentRisk * RiskMpOnLoss;
    }
    if (CurrentRisk > MaxRisk)
    {
        CurrentRisk = MaxRisk;
    }
     if (profit > 0)
    {
        CurrentRisk = RiskPercent;
    }
    double lotsize = MarketInfo(Symbol(),MODE_LOTSIZE) / 1;
    double pipsize = 100 * 10;
    double maxlots = AccountEquity() / 100 * CurrentRisk / lotsize * pipsize;
    if (StopLoss == 0) Print("OrderSend() error - stoploss can not be zero");
    double lots = maxlots / StopLoss * 10;
    
    // calculate lot size based on current risk
    double lotvalue = 0.001;
    double minilot = MarketInfo(Symbol(), MODE_MINLOT);
    int powerscount = 0;
    while (minilot < 1)
    {
        minilot = minilot * MathPow(10, powerscount);
        powerscount++;
    }
    lotvalue = NormalizeDouble(lots, powerscount - 1);
    
    if (lotvalue < MarketInfo(Symbol(), MODE_MINLOT))    // make sure lot is not smaller than allowed value
    {
        lotvalue = MarketInfo(Symbol(), MODE_MINLOT);
    }
    if (lotvalue > MarketInfo(Symbol(), MODE_MAXLOT))    // make sure lot is not greater than allowed value
    {
        lotvalue = MarketInfo(Symbol(), MODE_MAXLOT);
    }

    
    int ticket = -1;
    if (true)
    ticket = OrderSend(Symbol(), OP_SELL, lotvalue, Bid, 4, 0, 0, "My Expert", MagicNumber, 0, Red);
    else
    ticket = OrderSend(Symbol(), OP_SELL, lotvalue, Bid, 4, stoploss, takeprofit, "My Expert", MagicNumber, 0, Red);
    if (ticket > -1)
    {
        if (true)
        {
            OrderSelect(ticket, SELECT_BY_TICKET);
            bool ret = OrderModify(OrderTicket(), OrderOpenPrice(), stoploss, takeprofit, 0, Red);
            if (ret == false)
            Print("OrderModify() error - ", ErrorDescription(GetLastError()));
        }
            
    }
    else
    {
        Print("OrderSend() error - ", ErrorDescription(GetLastError()));
    }
}
 
clerin6:

Just had a brief glimpse at your code.

The order modify error is most likely from where you use OrderModify()

... not from where you are using OrderSelect() to get the order sl.

It looks like you are selecting the position by cycling through your ENTIRE trade history. Remember that the history is indexed forwards, so the earliest trade in your trade history is number 0.

(Also remember that the trade history is determined by the time period you select in metatrader, and the history backdata saved by your broker, so it may not show all the trades you ever placed on that account.)

Rather than cycling from the past to the present, you could save time by cycling from the present to the past.

Even better, if it suits your system, you could keep a separate note of the sl you require as a separate double variable, and only update it when required. That way you would avoid the hassle and time of checking previous orders, and could query that variable directly.

Either way, make sure you are not trying to set a sl or tp on the wrong sides of your open price. It does not seem as though you are checking this with the code before placing the order, though I could be wrong.

Remember that the sl and tp are the "full" price values, not the number of pips for offset from those values.





Perhaps my issue is therefore that I am trying to place the sl and tp (x) amount of pips from the new order but it wont execute as it is using fixed price values which would lead to order modify errors. Do you know if there is a way to use/store the previous stop loss value in number of pips rather than price?
 
gangsta1:
Perhaps my issue is therefore that I am trying to place the sl and tp (x) amount of pips from the new order but it wont execute as it is using fixed price values which would lead to order modify errors. Do you know if there is a way to use/store the previous stop loss value in number of pips rather than price?

Just calculate it using the OrderOpenPrice()
 
RaptorUK:
Just calculate it using the OrderOpenPrice()

As in OrderOpenPrice() - OrderStopLoss() ??

Im thinking if the buy OrderOpenPrice was say 1.2500 and the stop loss was hit at 1.0000, then the OrderOpenPrice() - OrderStopLoss() would be 0.2500. I guess I would then need to normalize the results? This would then give me a pip value for the stop that I could use in the new trade. Would you mind helping me write the calculation code and showing me where it should go?

 

Assuming you have addressed the apparent problem with the conditional which says "if (true)", presumably you would then need to insert something here:

    else
    ticket = OrderSend(Symbol(), OP_SELL, lotvalue, Bid, 4, stoploss, takeprofit, "My Expert", MagicNumber, 0, Red);

... between "else" and the next line.

First figure out the direction of the previous trade using OrderType(), then use that to figure out whether you should minus OrderOpenPrice() from OrderStopLoss() or vice versa. (Or simply minus them blind and use MathAbs().)

Then figure out the direction of the trade you are about to insert the sl into (which in your example is a sell order). Then take the current price (Ask for long, Bid for short) and add or subtract the sl from that accordingly, then place that in the sl slot of the order command.

Make sure the tp is similarly correct and in the right direction. You may want to use RefreshRates() before you send the order as well, if your code took a long time to get there from the tick it started on.

Also, remember to make sure you are using the correct number of decimal places for your broker, by using NormalizeDouble(), otherwise you will get a whole new set of errors.

 

Think I got it at last.. The code below seems to do the trick.

double previousstop = 0;

previousstop = (OrderOpenPrice()-OrderStopLoss());

double stop = (OrderOpenPrice()+previousstop);

ticket = OrderSend(Symbol(), OP_SELL, lotvalue, Bid, 4, stop, TP, "My Expert", MagicNumber, 0, Red);

 
gangsta1:

Think I got it at last.. The code below seems to do the trick.

Not yet . . . keep working at it . . . .

stop = ( 2 * OrderOpenPrice() )  -  OrderStopLoss()

. . . doesn't make much sense to me.

 

The code I used finds the previous stop loss value in pips by subtracting the open price of that order with the stop loss value in price and stores it in previousstop.

Then I get the stop loss value in price (stored in stop) by adding the previous stop value in pips to the open price of the new order.

Does that make sense. This is of course for a buy order. It seems to work although it may not be the ideal solution.