stop order problem

Questions about MultiCharts and user contributed studies.
LA901
Posts: 18
Joined: 15 Dec 2014
Has thanked: 7 times
Been thanked: 4 times

stop order problem

Postby LA901 » 17 Jan 2015

The code below replicates a simplified version of something I'm trying to achieve.

In the example below, if the close of the current tick breaks the last bar high then I want to set a buy stop order based on that close price + 10 pips (0.0010) - this is for backtesting purposes only.

But this doesn't work for some reason?

Code: Select all

[IntrabarOrderGeneration = true];

variables:
limitprice (0),
stopprice (0),
EP1 (0),
intrabarpersist bid (0);

bid = close ; //tick close not bar close
EP1 = high[1];

condition1 = bid > high[1] ;

if condition1 then
buy ("LongS") 1000 contracts next bar (bid + 0.0010) stop ;

if marketposition > 0 then
begin

limitprice = PosTradeEntryPrice(0,0) + 0.0020 ;
stopprice = PosTradeEntryPrice(0,0) - 0.0020 ;

sell ("SL") next bar stopprice stop;
sell ("TP") next bar limitprice limit;

end ;

User avatar
TJ
Posts: 7740
Joined: 29 Aug 2006
Location: Global Citizen
Has thanked: 1033 times
Been thanked: 2221 times

Re: stop order problem

Postby TJ » 17 Jan 2015

The code below replicates a simplified version of something I'm trying to achieve.
::
What is your chart resolution?

User avatar
JoshM
Posts: 2195
Joined: 20 May 2011
Location: The Netherlands
Has thanked: 1544 times
Been thanked: 1565 times
Contact:

Re: stop order problem

Postby JoshM » 18 Jan 2015

In the example below, if the close of the current tick breaks the last bar high then I want to set a buy stop order based on that close price + 10 pips (0.0010) - this is for backtesting purposes only.

Code: Select all

[IntrabarOrderGeneration = true];

(...)

bid = close ; //tick close not bar close

(...)

condition1 = bid > high[1] ;

(....)

if condition1 then
buy ("LongS") 1000 contracts next bar (bid + 0.0010) stop ;

(...)
It looks like your stop is not hit because, on every new price update that's above the previous high, it's set to the previous tick + 0.0010. This way it can only be hit when the next tick has a considerable gap (>= +0.0010) compared to the previous tick.

What I'd do is only calculate the stop price once when a certain condition (in this case, `bid > High[1]`) happens. That way the stop is more static and not updated on consecutive ticks.

For example:

Code: Select all

[IntrabarOrderGeneration = true];

Variables:
IntraBarPersist stopBidPrice(0),
bid(0),
IntraBarPersist prevBid(0);

bid = close ; //tick close not bar close

// Only calculate the stop price based on the bid once:
// the first time when bid is higher than the previous high
if (bid > high[1]) and (prevBid < High[1]) then begin
condition1 = true;
stopBidPrice = bid + 0.0010;
end;

if condition1 then
buy ("LongS") 1000 contracts next bar stopBidPrice stop ;

prevBid = bid;

LA901
Posts: 18
Joined: 15 Dec 2014
Has thanked: 7 times
Been thanked: 4 times

Re: stop order problem

Postby LA901 » 24 Jan 2015

In the example below, if the close of the current tick breaks the last bar high then I want to set a buy stop order based on that close price + 10 pips (0.0010) - this is for backtesting purposes only.

Code: Select all

[IntrabarOrderGeneration = true];

(...)

bid = close ; //tick close not bar close

(...)

condition1 = bid > high[1] ;

(....)

if condition1 then
buy ("LongS") 1000 contracts next bar (bid + 0.0010) stop ;

(...)
It looks like your stop is not hit because, on every new price update that's above the previous high, it's set to the previous tick + 0.0010. This way it can only be hit when the next tick has a considerable gap (>= +0.0010) compared to the previous tick.

What I'd do is only calculate the stop price once when a certain condition (in this case, `bid > High[1]`) happens. That way the stop is more static and not updated on consecutive ticks.

For example:

Code: Select all

[IntrabarOrderGeneration = true];

Variables:
IntraBarPersist stopBidPrice(0),
bid(0),
IntraBarPersist prevBid(0);

bid = close ; //tick close not bar close

// Only calculate the stop price based on the bid once:
// the first time when bid is higher than the previous high
if (bid > high[1]) and (prevBid < High[1]) then begin
condition1 = true;
stopBidPrice = bid + 0.0010;
end;

if condition1 then
buy ("LongS") 1000 contracts next bar stopBidPrice stop ;

prevBid = bid;
Just had a chance to look at this again properly.

Thanks for the post above, it lead me to understanding why my original code was incorrect and how MC worked in this regards.

The code I actually used to get this working as intended was slightly different to that above (as this would still lead to the stop order being updated if bid moved above the 1st bid that lead to the condition to be true but lower than the stop order price). So for anyone else who encountered the same issue and didn't know why, if you follow TradeSentLong variable in the code below you should be able to see that the Stopentryprice generated when the condition is 1st true will never be updated until it leads to an open trade (i.e. MP>0).

Code: Select all

[IntrabarOrderGeneration = true]

variables:

intrabarpersist mybid (0),
intrabarpersist stopentryprice (0),
intrabarpersist TradeSentLong (0) ;

mybid = close ;

//Sets stop price when condition 1st becomes true - it cannot be changed until TradeSentLong is reset.
if mybid > high[1] and TradeSentLong = 0 then
begin
condition1 = true;
stopentryprice = mybid + 0.0001 ;
TradeSentLong = 1;
end;

If TradeSentLong = 1 then
begin
buy ("long") 100 contracts next bar stopentryprice stop ;
end;

//Reset Tradesentlong
if marketposition > 0 then
TradeSentLong = 0;


//debugging
Print (Date:7:0, ",",
Time:4:0, ",",
NumToStr ( mybid, 5) , ",",
NumToStr (stopentryprice, 5));

LA901
Posts: 18
Joined: 15 Dec 2014
Has thanked: 7 times
Been thanked: 4 times

Re: stop order problem

Postby LA901 » 26 Jan 2015

To help others who look to trade breakouts via stop orders whereby they want to trade the initial continuation move when price first breaks the breakout price (in this case previous bar high) I've elaborated on the code in the previous post.

The key is needing to ensure a) capture 1st time price breaks the breakout price, b) ensuring price has not moved significantly above the breakout price and c) time since breakout occurred is not a significant time later.

The steps you need to go through to achieve the above are:

1. Store the datetime of when price first breaks the previous bar high and importantly ensure this can't be updated until a new breakout price has formed - which in this case would be after a new bar has closed and thus a new High[1].

2. Store breakout bar number (so can reset when a new bar forms in line with the above).

3. If price is still within the set range after 1st breaking the previous bar high (in this case <2 pips above the previous bar high) then set stop order price.

4. If time since initial breakout is < allowed time (in this case 2mins since breakout) then place stop order.

5. Cancel stop order if allowed time since breakout has been exceeded.

6. Reset looking for initial breakout when a new bar is completed and thus have a new reference high[1].

Code: Select all

[IntrabarOrderGeneration = true]

variables:

intrabarpersist mybid (0),
intrabarpersist stopentryprice (0),
intrabarpersist TradeSentLong (0),
intrabarpersist TargetPrice (0),
intrabarpersist StopLossPrice (0),
intrabarpersist stoplogging (false),
intrabarpersist BODT (0),
intrabarpersist lookforlong (0),
intrabarpersist BOBarnum (0),
mybidextreme (0);

mybid = close ; //for backtesting only - in live trading mybid=insidebid
stoplogging = false ;
mybidextreme = high[1] + 0.0002 ; //ensures bid price that 1st crosses previous bar high isn't too high

//Store BO datetime and bar number when bid price 1st crosses previous bar high
if mybid > high[1] and lookforlong = 0 then
begin
BODT = datetime + (2/1440); //2mins after bid price 1st crosses previous bar high
BOBarNum = barnumber ; //remember bar counting starts after maxbarsback
lookforlong = 1 ; //ensures only capturing 1st time price breaks high as not reset until a new bar and thus a new breakout price is formed
end;

//Ensures bid price that broke previous bar high is a maximum of 2 pips beyond high and sets stoporder price
if mybid > high[1] and mybid < mybidextreme and TradeSentLong = 0 and lookforlong = 1 then
begin
stopentryprice = mybid + 0.0002;
TradeSentLong = 1;
end;

//Keep stop order in place < BODT time from when bid 1st crossed previous bar high i.e. < 2mins
If TradeSentLong = 1 and datetime < BODT and stoplogging = false then
begin
buy ("long") 100 contracts next bar stopentryprice stop ;

//debugging
Print (Date:7:0, ",",
Time:4:0, ",",
NumToStr ( mybid, 5) , ",",
NumToStr (stopentryprice, 5), ",",
NumToStr (High[1], 5), ",",
datetimetostring(BODT), ",",
NumToStr (currentbar,0), ",",
NumToStr (BOBarnum,0));
end;

//Set TP, SL and reset TSL
if marketposition > 0 then
begin
TradeSentLong = 0 ;
TargetPrice = PosTradeEntryPrice(0,0) + 0.0010 ;
StopLossPrice = PosTradeEntryPrice(0,0) - 0.0010 ;
stoplogging = true ;

sell ("TP") 100 contracts next bar TargetPrice limit ;
sell ("SL") 100 contracts next bar StopLossPrice Stop ;
end;

//Reset TSL if BODT time reached
if TradeSentLong = 1 and datetime >= BODT then
TradeSentLong = 0 ;

//Reset Lookforlong when a new bar completed
if currentbar > BOBarnum then
Lookforlong = 0 ;
General Observations:
1. Mybid refers to tick close in backtest (with Bar Magnifier set to 1 tick precision), in live markets you would use mybid = insidebid (can use GetAppInfo etc within an if statement to switch between live trading and backtesting).

2. In line with the above note that insidebid is NOT updated during a tick and there is no definitive way of obtaining the actual latest bid price. You can use Recalclastbarafter to force an update if ticks are updated less than 0.1 seconds - it's a bit of a hack really though compared to just being able to call the latest bid price at various points within a script. Thus the first reported bid within the script that breaks the previous bar high is the same bid price used within the max entry range, therefore if the 1st bid is higher than this range it won't trade - covers against unusually high slippage/illiquid markets. If using market orders this in my experience means you suffer more slippage on average as you can't do a proper slippage check just prior to entry as insidebid price script refers too is potentially outdated. Recalclastbarafter is not useful in backtesting of course as mybid = tick closing price i.e. it's a static price.

3. I try not to refer to marketposition within conditions and resets if possible. There can be latency between script giving the signal to enter a trade and a trade opening and in meantime a new signal could be created thus updating values before marketposition has changed to 1 or -1. Thus you need to make sure that new values can't be created due this latency.

Also have to consider what happens if an order is rejected, how does your script handle resets if MP doesn't change i.e. don't always assume a signal will actually lead to a change in MP. Hint - you can't just use if MP = 0 because of the potential latency issue mentioned above.


Return to “MultiCharts”