Skip to content

Commit

Permalink
All transactions should be treated with the same stop-loss mechanism
Browse files Browse the repository at this point in the history
Previously, only the first transaction was protected by a stop-loss or
trailing stop-loss. It also didn't allow for parallel (trailing) stop
orders.
  • Loading branch information
szotsaki committed Dec 28, 2024
1 parent 0981ee5 commit 7b6353f
Showing 1 changed file with 19 additions and 26 deletions.
45 changes: 19 additions & 26 deletions python/fastquant/strategies/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,10 @@ def __init__(self):
self.price_bought = 0

# Initialize stoploss order
self.stoploss_order = None
self.stoploss_orders = []

# Initialize stoploss trail order
self.stoploss_trail_order = None
self.stoploss_trail_orders = []

def buy_signal(self):
return False
Expand Down Expand Up @@ -400,25 +400,21 @@ def next(self):
stop_price = self.data.close[0] * (1.0 - self.stop_loss)
if self.transaction_logging:
self.log("Stop price: {}".format(stop_price))
self.stoploss_order = self.sell(
self.stoploss_orders.append(self.sell(
exectype=bt.Order.Stop,
price=stop_price,
size=final_size,
)
))

if self.stop_trail:
# Create a stoploss trail order if None
if self.stoploss_trail_order is None:
if self.transaction_logging:
self.log("Stop trail: {}".format(self.stop_trail))
self.stoploss_trail_order = self.sell(
exectype=bt.Order.StopTrail,
trailpercent=self.stop_trail,
size=final_size,
)
# Cancel existing stoploss trail order
else:
self.cancel(self.stoploss_trail_order)
if self.transaction_logging:
self.log("Stop trail: {}".format(self.stop_trail))
self.stoploss_trail_orders.append(self.sell(
exectype=bt.Order.StopTrail,
trailpercent=self.stop_trail,
size=final_size,
))

# Buy based on the opening price of the next closing day (only works "open" data exists in the dataset)
else:
Expand All @@ -443,20 +439,20 @@ def next(self):
stop_price = self.data.close[0] * (1.0 - self.stop_loss)
if self.transaction_logging:
self.log("Stop price: {}".format(stop_price))
self.stoploss_order = self.sell(
self.stoploss_orders.append(self.sell(
exectype=bt.Order.Stop,
price=stop_price,
size=final_size,
)
))

if self.stop_trail:
if self.transaction_logging:
self.log("Stop trail: {}".format(self.stop_trail))
self.stoploss_trail_order = self.sell(
self.stoploss_trail_orders.append(self.sell(
exectype=bt.Order.StopTrail,
trailpercent=self.stop_trail,
size=final_size,
)
))

elif self.sell_signal() and (self.strategy_position in [1, -1, None]):
self.strategy_position = 0 if self.strategy_position in [1, -1] else None
Expand Down Expand Up @@ -531,13 +527,10 @@ def next(self):
size=int((self.init_cash / self.dataopen[1]) * self.sell_prop)
)

# Explicitly cancel stoploss order
if self.stoploss_order:
self.cancel(self.stoploss_order)

# Explicitly cancel stoploss trail order
if self.stoploss_trail_order:
self.cancel(self.stoploss_trail_order)
# Explicitly cancel active stop-loss (trail) orders
for order in self.stoploss_orders + self.stoploss_trail_orders:
if order.status not in ["Completed", "Canceled", "Expired", "Rejected"]:
self.cancel(order)

elif self.take_profit_signal():
# Take profit
Expand Down

0 comments on commit 7b6353f

Please sign in to comment.