Skip to content

Commit fc54771

Browse files
committed
Raises error if sell/cover_all_shares is called without open position.
1 parent 96f0609 commit fc54771

File tree

3 files changed

+18
-7
lines changed

3 files changed

+18
-7
lines changed

src/pybroker/context.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -829,7 +829,9 @@ def sell_all_shares(self):
829829
"""Sells all long shares of :attr:`.ExecContext.symbol`."""
830830
pos = self.long_pos()
831831
if pos is None:
832-
return
832+
raise ValueError(
833+
f"sell_all_shares failed: No long position for {self.symbol}"
834+
)
833835
self.sell_shares = pos.shares
834836
self._portfolio.remove_stops(pos)
835837
self._exiting_pos = True
@@ -838,7 +840,9 @@ def cover_all_shares(self):
838840
"""Covers all short shares of :attr:`.ExecContext.symbol`."""
839841
pos = self.short_pos()
840842
if pos is None:
841-
return
843+
raise ValueError(
844+
f"cover_all_shares failed: No short position for {self.symbol}"
845+
)
842846
self.cover_shares = pos.shares
843847
self._portfolio.remove_stops(pos)
844848
self._exiting_pos = True
@@ -1304,6 +1308,7 @@ def to_result(self) -> Optional[ExecResult]:
13041308
"sell_shares or hold_bars must be set when "
13051309
"sell_fill_price is set."
13061310
)
1311+
13071312
if self.buy_shares is None and self.sell_shares is None:
13081313
if (
13091314
self.stop_loss is not None

tests/test_context.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,11 @@ def test_sell_all_shares(ctx_with_pos):
263263

264264

265265
def test_sell_all_shares_when_no_position(ctx):
266-
ctx.sell_all_shares()
267-
assert ctx.sell_shares is None
266+
with pytest.raises(
267+
ValueError,
268+
match=re.escape("sell_all_shares failed: No long position for SPY"),
269+
):
270+
ctx.sell_all_shares()
268271

269272

270273
def test_cover_all_shares(ctx_with_pos):
@@ -274,8 +277,11 @@ def test_cover_all_shares(ctx_with_pos):
274277

275278

276279
def test_cover_all_shares_when_no_position(ctx):
277-
ctx.cover_all_shares()
278-
assert ctx.buy_shares is None
280+
with pytest.raises(
281+
ValueError,
282+
match=re.escape("cover_all_shares failed: No short position for SPY"),
283+
):
284+
ctx.cover_all_shares()
279285

280286

281287
def test_model(ctx, trained_models, symbol):

tests/test_strategy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2378,7 +2378,7 @@ def test_backtest_when_no_stops(self, data_source_df):
23782378
def exec_fn(ctx):
23792379
if ctx.bars == 1:
23802380
ctx.buy_shares = 100
2381-
elif ctx.bars > 30:
2381+
elif ctx.long_pos() and ctx.bars > 30:
23822382
ctx.sell_all_shares()
23832383

23842384
strategy = Strategy(data_source_df, START_DATE, END_DATE)

0 commit comments

Comments
 (0)