fix trend,zt

This commit is contained in:
2026-09-06 13:12:48 +08:00
parent bcc6f02398
commit 2eafbb8303
15 changed files with 502 additions and 480 deletions

View File

@@ -8,22 +8,29 @@ import math
from libs.grid_take_profit import GridState
from sdk import OP_BUY, OP_SELL, PositionItem
from .order import PlaceOrderRequest
from .runtime import Runtime
from .state import PendingOrder, READY, SOLD
from libs.order import PlaceOrderRequest
from libs.runtime import Runtime
from .state import PendingOrder, READY, SOLD, TState
def manage_positions(run: Runtime, ticks, positions: list[PositionItem], available: float,
today: str, force_buy_back: bool = False) -> float:
def manage_positions(
run: Runtime,
state_store: TState,
ticks,
positions: list[PositionItem],
available: float,
today: str,
force_buy_back: bool = False,
) -> float:
"""遍历本地底仓记录;全部卖出后即使持仓快照为空,也必须处理买回。"""
by_code = {position.stock_code: position for position in positions}
for code, state in list(run.state.items.items()):
for code, state in list(state_store.items.items()):
try:
now = datetime.now()
if now.hour >= 15:
break
force_buy_back = force_buy_back or (now.hour, now.minute) >= (14, 50)
if code in run.account_cfg.excluded_codes or run.state.busy(code):
if code in run.account_cfg.excluded_codes or state_store.busy(code):
continue
if run.orders.busy(code, "BUY") or run.orders.busy(code, "SELL"):
continue
@@ -36,39 +43,65 @@ def manage_positions(run: Runtime, ticks, positions: list[PositionItem], availab
expected_qty = state.base_qty - state.sell_qty + state.buy_qty
# 快照延迟或手动增减仓不能当作新的做 T 信号,先核对数量差异。
if actual_qty != expected_qty:
log.warning("[ZT 持仓] %s 数量不符,记录=%d,实际=%d,暂停交易", code, expected_qty, actual_qty)
log.warning(
"[ZT 持仓] %s 数量不符,记录=%d,实际=%d,暂停交易",
code,
expected_qty,
actual_qty,
)
continue
if state.phase == SOLD:
available = _try_buy_back(run, state, price, available, today, force_buy_back)
available = _try_buy_back(
run, state_store, state, price, available, today, force_buy_back
)
elif state.phase == READY and position and not force_buy_back:
if price <= run.account_cfg.zt_max_price:
_try_sell(run, state, position, price, today)
_try_sell(run, state_store, state, position, price, today)
except Exception:
log.exception("[ZT 持仓] %s 处理异常,继续后续证券", code)
return available
def _try_sell(run: Runtime, state, position: PositionItem, price: float, today: str) -> None:
def _try_sell(
run: Runtime,
state_store: TState,
state,
position: PositionItem,
price: float,
today: str,
) -> None:
"""基于独立保存的底仓成本,用跨轮最高盈利网格判断做 T 卖出。"""
if state.base_cost <= 0:
return
pnl_rate = (price - state.base_cost) / state.base_cost * 100
key = f"{run.account_cfg.account_id}:{state.code}:{today}"
observation = run.sell_tracker.observe(key, pnl_rate)
observation = run.profit_tracker.observe(key, pnl_rate)
if observation.state != GridState.RETREAT:
return
volume = min(position.can_use_volume, int(state.base_qty * run.account_cfg.zt_sell_ratio))
volume = min(
position.can_use_volume, int(state.base_qty * run.account_cfg.zt_sell_ratio)
)
volume = volume // 100 * 100
if volume <= 0:
return
order_id = run.orders.new_order_id("t-sell")
request = PlaceOrderRequest(OP_SELL, state.code, volume, order_id, "zt", kind="sell")
run.state.new_order(PendingOrder(order_id, state.code, "sell", volume, today))
request = PlaceOrderRequest(
OP_SELL, state.code, volume, order_id, "zt", kind="sell"
)
state_store.new_order(PendingOrder(order_id, state.code, "sell", volume, today))
if run.orders.place(run.client, request):
log.info("[ZT 卖出] %s %d 股,等待成交后确定买回数量和价格", state.code, volume)
def _try_buy_back(run: Runtime, state, price: float, available: float, today: str, force: bool) -> float:
def _try_buy_back(
run: Runtime,
state_store: TState,
state,
price: float,
available: float,
today: str,
force: bool,
) -> float:
"""按实际卖出均价下跌后反弹买回;尾盘不再受下跌幅度、反弹及价格上限限制。"""
target = state.sell_price * (1 - run.account_cfg.zt_buy_fall_pct / 100)
if not force and (price > target or price > run.account_cfg.zt_max_price):
@@ -78,17 +111,22 @@ def _try_buy_back(run: Runtime, state, price: float, available: float, today: st
if volume <= 0 or amount > available:
log.warning("[ZT 买回] %s 买回资金不足或数量无效,保留未完成轮次", state.code)
return available
if not force and not run.buy_watch.triggered("ZT 买回", state.code, price):
if not force and not run.add_watch.triggered("ZT 买回", state.code, price):
return available
order_id = run.orders.new_order_id("t-buy")
request = PlaceOrderRequest(OP_BUY, state.code, volume, order_id, "zt", kind="buy")
run.state.new_order(PendingOrder(order_id, state.code, "buy", volume, today))
state_store.new_order(PendingOrder(order_id, state.code, "buy", volume, today))
# pending 已落盘,任何请求结果都预留资金;下一轮再从柜台快照确认。
available -= amount
try:
if run.orders.place(run.client, request):
run.buy_watch.forget(state.code)
log.info("[ZT 买回] %s %d 股,%s", state.code, volume, "尾盘强制买回" if force else "下跌后反弹")
run.add_watch.forget(state.code)
log.info(
"[ZT 买回] %s %d 股,%s",
state.code,
volume,
"尾盘强制买回" if force else "下跌后反弹",
)
except Exception:
log.exception("[ZT 买回] %s 请求结果未知,保留 pending 和预算", state.code)
return available