"""日内先卖后买的做 T 规则。""" from __future__ import annotations import logging from libs.grid_take_profit import GridState from sdk import OP_BUY, OP_SELL, PositionItem from strategy.trend.order import PlaceOrderRequest from .state import BUYING, READY, SELLING, SOLD def manage_positions(run, ticks, positions: list[PositionItem], available: float, today: str, force_buy_back: bool = False) -> None: for position in positions: code = position.stock_code tick = ticks.get(code) if not code or code in run.account_cfg.excluded_codes or tick is None: continue price = tick.last_price if price <= 0 or price > run.account_cfg.zt_max_price: continue try: state = run.state.get(code) except KeyError: continue if state.phase == READY and not force_buy_back: _try_sell(run, state, position, price, today) elif state.phase == SOLD: _try_buy_back(run, state, price, available, today, force_buy_back) def _try_sell(run, state, position: PositionItem, price: float, today: str) -> None: if state.base_cost <= 0 or run.orders.busy(state.code, "SELL"): return pnl_rate = (price - state.base_cost) / state.base_cost * 100 observation = run.sell_tracker.observe(f"{run.account_cfg.account_id}:{state.code}", pnl_rate) if observation.state != GridState.RETREAT: return volume = min(position.can_use_volume, int(state.base_qty * run.account_cfg.zt_sell_ratio) // 100 * 100) if volume <= 0: return order_id = run.orders.new_order_id("t-sell") request = PlaceOrderRequest(run.client, OP_SELL, state.code, volume, order_id, run.account_cfg.strategy) if not run.orders.place(request): return state.trade_date, state.phase = today, SELLING state.sell_order_id, state.sell_qty, state.sell_price = order_id, volume, price run.state.set(state) run.state.save() logging.info("[ZT 卖出] %s %d 股,网格回撤触发", state.code, volume) def _try_buy_back(run, state, price: float, available: float, today: str, force: bool) -> None: target = state.sell_price * (1 - run.account_cfg.zt_buy_fall_pct / 100) if (not force and price > target) or run.orders.busy(state.code, "BUY"): return if state.sell_qty <= 0 or price * state.sell_qty > available: return if not force and not run.buy_watch.triggered("ZT 买回", state.code, price): return order_id = run.orders.new_order_id("t-buy") request = PlaceOrderRequest(run.client, OP_BUY, state.code, state.sell_qty, order_id, run.account_cfg.strategy) if not run.orders.place(request): return state.trade_date, state.phase, state.buy_order_id = today, BUYING, order_id run.state.set(state) run.state.save() run.buy_watch.forget(state.code) reason = "尾盘强制买回" if force else f"回撤 {run.account_cfg.zt_buy_fall_pct:.2f}% 后反弹确认" logging.info("[ZT 买回] %s %d 股,%s", state.code, state.sell_qty, reason)