@@ -150,8 +150,12 @@ def __init__(
150150 self .loss_ticks = loss_ticks
151151 self .trail_points_ticks = trail_points_ticks
152152
153- # Check if this is a market order (no limit, stop, or trail price)
154- self .is_market_order = self .limit is None and self .stop is None
153+ # Check if this is a market order (no limit, stop, trail, or tick-based prices)
154+ self .is_market_order = (self .limit is None and self .stop is None
155+ and self .trail_price is None
156+ and self .profit_ticks is None
157+ and self .loss_ticks is None
158+ and self .trail_points_ticks is None )
155159
156160 self .cancelled = False
157161 self .bar_index = - 1 # Will be set when order is added to position
@@ -842,9 +846,11 @@ def _fill_order(self, order: Order, price: float, h: float, l: float):
842846 self .open_commission = 0.0
843847
844848 # Cancel all exit orders when position is closed (TradingView behavior)
845- # Exit orders without from_entry are canceled when position is flat
849+ # Skip exits that have a pending entry (needed during position flips)
846850 exit_orders_to_remove = list (self .exit_orders .values ())
847851 for exit_order in exit_orders_to_remove :
852+ if exit_order .order_id in self .entry_orders :
853+ continue
848854 self ._remove_order (exit_order )
849855
850856 # Increment intraday filled orders counter for ALL filled orders
@@ -1306,21 +1312,29 @@ def process_orders(self):
13061312 if entry_price is not None :
13071313 # Determine direction from the order
13081314 direction = 1.0 if order .size < 0 else - 1.0 # Exit order size is negative of position
1315+ changed = False
13091316
13101317 # Calculate limit from profit_ticks if specified
13111318 if order .profit_ticks is not None and order .limit is None :
13121319 order .limit = entry_price + direction * syminfo .mintick * order .profit_ticks
13131320 order .limit = _price_round (order .limit , direction )
1321+ changed = True
13141322
13151323 # Calculate stop from loss_ticks if specified
13161324 if order .loss_ticks is not None and order .stop is None :
13171325 order .stop = entry_price - direction * syminfo .mintick * order .loss_ticks
13181326 order .stop = _price_round (order .stop , - direction )
1327+ changed = True
13191328
13201329 # Calculate trail_price from trail_points_ticks if specified
13211330 if order .trail_points_ticks is not None and order .trail_price is None :
13221331 order .trail_price = entry_price + direction * syminfo .mintick * order .trail_points_ticks
13231332 order .trail_price = _price_round (order .trail_price , direction )
1333+ changed = True
1334+
1335+ # Update orderbook only when prices were actually calculated
1336+ if changed :
1337+ self .orderbook .add_order (order )
13241338
13251339 # Check for stop/limit orders that should be converted to market orders
13261340 for order in self .orderbook .iter_orders ():
@@ -1405,6 +1419,31 @@ def process_orders(self):
14051419 else :
14061420 self .fill_order (order , fill_price , self .l , self .o )
14071421
1422+ # Convert tick-based exit prices for entries that just filled this bar
1423+ for order in self .exit_orders .values ():
1424+ entry_price = None
1425+ for trade in self .open_trades :
1426+ if trade .entry_id == order .order_id :
1427+ entry_price = trade .entry_price
1428+ break
1429+ if entry_price is not None :
1430+ direction = 1.0 if order .size < 0 else - 1.0
1431+ changed = False
1432+ if order .profit_ticks is not None and order .limit is None :
1433+ order .limit = entry_price + direction * syminfo .mintick * order .profit_ticks
1434+ order .limit = _price_round (order .limit , direction )
1435+ changed = True
1436+ if order .loss_ticks is not None and order .stop is None :
1437+ order .stop = entry_price - direction * syminfo .mintick * order .loss_ticks
1438+ order .stop = _price_round (order .stop , - direction )
1439+ changed = True
1440+ if order .trail_points_ticks is not None and order .trail_price is None :
1441+ order .trail_price = entry_price + direction * syminfo .mintick * order .trail_points_ticks
1442+ order .trail_price = _price_round (order .trail_price , direction )
1443+ changed = True
1444+ if changed :
1445+ self .orderbook .add_order (order )
1446+
14081447 # Adapt orphaned exits from rejected entries to new position (TradingView behavior)
14091448 # When strategy.exit() is called without from_entry, TV keeps the exit even after
14101449 # its entry is rejected by margin. The exit adapts to close any new position that opens.
0 commit comments