CODESCRIPT

Pending orders

A pending order is one that does not fill straight away. It rests at a price level and waits there until price arrives. This page shows how to place one, how to withdraw it, and why it sometimes never fills at all.

When a condition fires you have two choices. You can take the price that is on the screen right now, or you can name a price and wait for it. The first is a market order, the second a pending order.

A pending order lets you hunt for a better entry price. The trade-off is real: price may never come to your level, and then no trade happens at all.

Market order or pending order

On its own, order places a market order. On the bar where the condition is true it does not look for a level, it simply fills. entryMarket does exactly the same job; the two names point to one function.

CODESCRIPT
// piyasa emri: kosul dogdugu barda beklemeden dolar
order(crossover(close, sma(close, 20)))
exit(crossunder(close, sma(close, 20)))
plot(sma(close, 20), "SMA20", "#2962ff")

The blue line is the 20-bar average. A buy mark appears where the close crosses above it, and the position closes where it crosses back below. Since nothing is waiting at a level, every signal turns into a trade.

CAUTION

order cannot hold an order at a level; it only takes a condition and a direction. To hang an order at a price, call enterLong or enterShort and pass limit or stop.

limit and stop: two ways of waiting

Give an entry a limit and you are waiting for a better price. Give it a stop and you are waiting for the move to prove itself. Which one sits above price and which below depends on the direction you are taking.

  • On a long entry, limit rests below price and fills if price comes down to it.
  • On a long entry, stop rests above price and fills if price rises through it.
  • On a short entry, limit rests above price and stop below; the rule simply mirrors.
  • In short, limit waits for the discount and stop waits for the break.

limit: buy if the level comes

In the script below, a buy order is placed when the close drops under the 20-bar average. It does not fill on the spot; it waits two percent under that average.

CODESCRIPT
// ortalamanin %2 altina asili alim emri
hedef = sma(close, 20) * 0.98
enterLong(crossunder(close, sma(close, 20)), limit=hedef)
exit(crossover(close, sma(close, 50)))
plot(hedef, "bekleyen seviye", "#ff9800")

The orange line is the level the order is waiting at. No buy mark appears on the crossing bar; it shows up only if price actually drops to the orange line, on the bar where the order fills.

stop: buy if it breaks

A stop order does the opposite. Nothing opens until price breaks upward. You pay more for the entry, but you have seen the move begin.

CODESCRIPT
// son 20 barin tepesi kirilirsa al
tepe = highest(high, 20)
enterLong(rsi(close, 14) > 55, stop=tepe)
exit(crossunder(close, sma(close, 20)))
plot(tepe, "kirilim seviyesi", "#2962ff")

The blue line is the highest of the last 20 bars. The order is armed while RSI is above 55 and fills only if price breaks up through that line. No break, no trade.

CAUTION

One entry cannot carry both limit and stop. One says come down, the other says break up; together they do not describe a single coherent wait, and the engine raises a clear error.

Naming the order: id

Passing an id gives the pending order a name. Once it has one, you can keep several orders on the list at the same time and manage each separately. The name has to be constant text; a name that shifts from bar to bar makes the order impossible to track.

ocaGroup ties the two faces of one setup together. When any order carrying the same group tag fills, the rest are removed from the list.

CODESCRIPT
// iki senaryo ayni anda bekler: dipten alim ve kirilimdan alim
dip = sma(close, 20) * 0.98
kirilim = highest(high, 20)
enterLong(rsi(close, 14) < 45, id="dip", limit=dip, ocaGroup="kurulum")
enterLong(rsi(close, 14) < 45, id="kirilim", stop=kirilim, ocaGroup="kurulum")
exit(crossunder(close, sma(close, 50)))

When RSI drops under 45, two orders go up at once: one fills if price falls, the other if price rises. Because they share an ocaGroup, the moment one fills the other is dropped and only a single trade opens.

NOTE

Issue a second order under the same id and the new one takes the old one's place instead of adding a second line. Want both waiting at once? Use two different names. With no id at all there is a single pending slot, and that order fills only while you are flat.

Withdrawing an order: cancel and cancelAll

If an order you placed is no longer wanted, you pull it back. cancel removes just the one you name. cancelAll clears everything that is waiting.

CODESCRIPT
// kurulum bozulursa bekleyen emri geri cek
dip = sma(close, 20) * 0.98
enterLong(crossunder(close, sma(close, 20)), id="dip", limit=dip)
cancel("dip", rsi(close, 14) > 60)
exit(crossover(close, sma(close, 50)))

The dip order is placed and waits for price. If RSI climbs past 60 the order leaves the list; even if price later reaches the level it will not fill, and that scenario's buy mark never appears.

CODESCRIPT
// gun donmeden once hem bekleyen girisi hem bekleyen cikisi temizle
enterLong(crossunder(close, sma(close, 20)), id="dip", limit=sma(close, 20) * 0.98)
exit(true, id="hedef", limit=close * 1.05)
exit(crossunder(close, sma(close, 50)))
cancelAll(hour == 23)

Through the day both a resting buy and a take-profit five percent higher sit on the list. On the bar where the hour turns 23, cancelAll wipes both. Any open position stays exactly where it was and closes only on the average cross.

CAUTION

Neither cancel nor cancelAll closes an open position. Both only remove orders that have not filled yet; to leave a position you use exit or closeAll. Watch out: cancelAll also clears resting exit orders, so your take-profit and stop-loss protection goes with them.

Why the order did not fill

You can see the order waiting on the chart, but no buy mark ever shows. Usually that is not a fault, it is the rule doing its work. These are the common reasons.

  • The order was only just armed on this bar. It cannot fill on its own bar; the earliest it can fill is the next one.
  • Price never came to the level. A pending order fills only if price genuinely trades through it.
  • Another level was reached first inside the same bar, and the sibling order in that ocaGroup was cancelled.
  • cancel or cancelAll ran and took the order off the list.
  • You issued a second order under the same id; the old one is gone and the level now waiting is the new one.
  • You used an unnamed pending order while a position was open. An unnamed order fills only when you are flat.

It never fills on its own bar

The engine walks each bar's opening first and runs your script afterwards. By the time the script arms a pending order, that bar's price path is already behind it. That is why the order is first tested on the next bar.

The rule is what keeps a backtest honest. Otherwise you would see a whole bar and then trade inside it, and the results would come out better than anything you could reach in real trading.

Price never reached the level

This is the most common reason and the easiest to check. Draw the level, mark the bars where price touches it, and the answer is right there on the chart.

CODESCRIPT
// bekleyen seviyeyi ciz ve fiyatin degdigi barlari isaretle
seviye = sma(close, 20) * 0.98
enterLong(crossunder(close, sma(close, 20)), id="dip", limit=seviye)
exit(crossover(close, sma(close, 50)))
plot(seviye, "bekleyen seviye", "#ff9800")
mark(low <= seviye, shape.circle, location.belowbar, "#26a69a", "degdi")

The orange line is where the order waits. On bars with a green circle underneath, price did drop to it. If you see no circles at all, the reason is settled: price simply never went there.

TIP

When an order refuses to fill, plot the level first. If it sits far off the chart the problem is not the order but the arithmetic that produced it, so bring the multiplier closer to price.

Another level came first inside the bar

A bar is not a single price. It travels a path from open to close, and pending orders are checked in sequence along that path. If two of your levels are seen on the same bar, the one that comes first on the path fills.

  • On an up bar the path runs open, low, high, close.
  • On a down bar the path runs open, high, low, close.
  • When both levels are seen on one bar, the earlier one on the path fills and the other is dropped.
  • On an exact tie the stop-loss goes first, a rule chosen deliberately to stay on the cautious side.
NOTE

Bar data does not record the true order in which price moved inside a bar; the path is assumed from the two rules above. So when both levels appear on one bar, judge the result across many samples rather than trusting a single bar.

The order of checks inside a bar

When several things could happen on one bar, the engine looks in this order. Pending entry orders come last, so if an exit filled ahead of them the picture may already have changed.

  • First the position's own stop-loss, take-profit and trailing stop levels are checked.
  • Next come the resting exit orders you armed with an id.
  • Pending entry orders are checked last.

What price the order fills at

A fill does not always land on the exact level you wrote. If the bar opens beyond your level, the order fills at the open, which hands you a better price than you asked for. If the bar opens short of the level and reaches it later, the fill lands on the level itself.

  • A limit order takes no slippage; you get your price or better.
  • A stop order takes slippage in the direction of the move, because you are joining a move that is already through the level.
  • You set the slippage rate with slippage and the trading cost with commission.
NOTE

If a verification margin is set for limit orders, touching the level is not enough; price has to go past it by that margin. When an order stubbornly refuses to fill, check that setting too.

Function reference

cancel(id[, when])

Returns nothing. It removes the pending order carrying the name you gave.

id
text
The name of the order to cancel. It must be constant text; a name that changes bar to bar is not allowed. The same name is looked up in both pending entries and resting exits.
when
condition
Optional. The bar on which the cancel runs. Leave it out and it runs on every bar. If no such order exists, nothing happens.

cancelAll([when])

Returns nothing. It clears every pending entry and resting exit together and leaves an open position untouched.

when
condition
Optional. The bar on which the sweep runs. Leave it out and it runs every bar, which means no order ever gets to wait.

order(koşul, yön?)

Returns nothing. It routes a market order on the bar where the condition is true. It is the same function as entryMarket.

koşul
condition
The position is opened on the bar where this is true. It takes no level, so there is no waiting.
yön
text
Optional. Pass short to go short; leave it out to go long. For risk settings such as stop-loss and take-profit, reach for enterLong or enterShort instead.