diff options
| author | TheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com> | 2026-04-01 18:36:18 +0900 |
|---|---|---|
| committer | TheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com> | 2026-04-01 18:36:18 +0900 |
| commit | b23aef3a9947d4d3d8e87b595ecf547159df7289 (patch) | |
| tree | c5c99869d300c4a1ace118a2dc03c5dfa3218499 | |
| parent | 5cee0686e421b1f21484c23e413692616e9e2ffa (diff) | |
feat(shared): add conviction, stop_loss, take_profit to Signal model
| -rw-r--r-- | services/backtester/src/backtester/engine.py | 7 | ||||
| -rw-r--r-- | shared/src/shared/models.py | 3 | ||||
| -rw-r--r-- | shared/tests/test_models.py | 29 |
3 files changed, 38 insertions, 1 deletions
diff --git a/services/backtester/src/backtester/engine.py b/services/backtester/src/backtester/engine.py index 8854b17..b03715d 100644 --- a/services/backtester/src/backtester/engine.py +++ b/services/backtester/src/backtester/engine.py @@ -90,7 +90,12 @@ class BacktestEngine: signal = self._strategy.on_candle(candle) if signal is not None: - simulator.execute(signal, timestamp=candle.open_time) + simulator.execute( + signal, + timestamp=candle.open_time, + stop_loss=signal.stop_loss, + take_profit=signal.take_profit, + ) # Calculate final balance including open positions valued at last candle close final_balance = simulator.balance diff --git a/shared/src/shared/models.py b/shared/src/shared/models.py index 0e8ca44..70820b5 100644 --- a/shared/src/shared/models.py +++ b/shared/src/shared/models.py @@ -45,6 +45,9 @@ class Signal(BaseModel): price: Decimal quantity: Decimal reason: str + conviction: float = 1.0 # 0.0 to 1.0, signal strength/confidence + stop_loss: Optional[Decimal] = None # Price to exit at loss + take_profit: Optional[Decimal] = None # Price to exit at profit created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc)) diff --git a/shared/tests/test_models.py b/shared/tests/test_models.py index 25ab4c9..b23d71d 100644 --- a/shared/tests/test_models.py +++ b/shared/tests/test_models.py @@ -94,6 +94,35 @@ def test_order_creation(): assert order.created_at is not None +def test_signal_conviction_default(): + """Test Signal defaults for conviction, stop_loss, take_profit.""" + from shared.models import Signal, OrderSide + + signal = Signal( + strategy="rsi", symbol="BTCUSDT", side=OrderSide.BUY, + price=Decimal("50000"), quantity=Decimal("0.01"), reason="test", + ) + assert signal.conviction == 1.0 + assert signal.stop_loss is None + assert signal.take_profit is None + + +def test_signal_with_stops(): + """Test Signal with explicit conviction, stop_loss, take_profit.""" + from shared.models import Signal, OrderSide + + signal = Signal( + strategy="rsi", symbol="BTCUSDT", side=OrderSide.BUY, + price=Decimal("50000"), quantity=Decimal("0.01"), reason="test", + conviction=0.8, + stop_loss=Decimal("48000"), + take_profit=Decimal("55000"), + ) + assert signal.conviction == 0.8 + assert signal.stop_loss == Decimal("48000") + assert signal.take_profit == Decimal("55000") + + def test_position_unrealized_pnl(): """Test Position unrealized_pnl computed property.""" from shared.models import Position |
