Close stale paper positions outside trend universe

This commit is contained in:
Codex
2026-06-21 23:30:10 +03:00
parent 8a211acf98
commit 6b9bddeb0a
2 changed files with 75 additions and 1 deletions
+27 -1
View File
@@ -7,7 +7,7 @@ from crypto_spot_bot.config import Settings
from crypto_spot_bot.execution import LiveBroker, PaperBroker
from crypto_spot_bot.learning import TradeLearner
from crypto_spot_bot.market_data import MarketData
from crypto_spot_bot.models import BotStatus, Signal, utc_now
from crypto_spot_bot.models import BotStatus, Signal, Ticker, utc_now
from crypto_spot_bot.patterns import PatternAnalyzer
from crypto_spot_bot.strategy import SpotStrategy
from crypto_spot_bot.storage import Storage
@@ -50,6 +50,7 @@ class CryptoSpotBot:
self.market.reset_stop()
if not self.market.symbols:
await self.market.bootstrap()
self._close_paper_positions_outside_symbol_universe()
self._update_patterns()
self._update_forecasts()
self.learner.refresh()
@@ -198,6 +199,31 @@ class CryptoSpotBot:
enriched["over_target_exposure"] = current_exposure > target_total + self.settings.min_position_usdt
return enriched
def _close_paper_positions_outside_symbol_universe(self) -> None:
if self.settings.strategy_mode != "trend_macd" or self.settings.trading_mode != "paper":
return
allowed_symbols = set(self.market.symbols or self.settings.symbols)
for position in list(self.broker.open_positions()):
if position.symbol in allowed_symbols:
continue
synthetic_ticker = Ticker(
symbol=position.symbol,
last_price=position.entry_price,
bid=position.entry_price,
ask=position.entry_price,
turnover_24h=0.0,
volume_24h=0.0,
change_24h=0.0,
)
self.broker.sell(
position,
synthetic_ticker,
"trend_macd: закрыта старая paper-позиция вне списка разрешенных пар",
)
self.storage.event(
f"{position.symbol}: старая paper-позиция закрыта при переходе на trend_macd"
)
def _reduction_candidate_id(self, prices: dict[str, float]) -> int | None:
rules = self._with_exposure_context(self.learner.state.adaptive_rules or {})
if not rules.get("reduce_exposure") or not rules.get("over_target_exposure"):