fix zt&state.py

This commit is contained in:
2026-09-12 13:42:23 +08:00
parent bcb03e2ed9
commit 7a7049ce44
9 changed files with 677 additions and 363 deletions

View File

@@ -2,14 +2,11 @@
import logging as log
import time
from contextlib import closing
from datetime import datetime
from pathlib import Path
from tempfile import TemporaryDirectory
from concurrent.futures import Future, ThreadPoolExecutor
import config
from libs.calc import trading_time
from libs.collector import collector_push
from libs.grid_take_profit import GridTrailingTracker
from libs.market import market_allow_open
from libs.order import OrderBook
@@ -18,9 +15,9 @@ from libs.runtime import Runtime
from libs.signal import SignalItem, init_signals
from libs.state import State
from libs.watch import DipWatch
from sdk import Client, DealItem, PositionItem
from sdk import Client
from .open import open_signal
from .positions import manage_positions, t_rounds
from .positions import manage_positions
from libs.snapshot import cache_portfolio
@@ -32,38 +29,35 @@ def StartZT() -> None:
)
executor = None
try:
portfolio = client.portfolio()
assets = portfolio.assets
positions = list(portfolio.positions.values())
state = State(Path(config.global_config.qmt_data_dir) / f'zt_{config.account_config.account_id}_state.db')
executor = ThreadPoolExecutor(max_workers=2, thread_name_prefix="zt")
run = Runtime(
client=client, global_cfg=config.global_config, account_cfg=config.account_config,
orders=OrderBook('zt'), open_watch=DipWatch(), add_watch=DipWatch(),
profit_tracker=GridTrailingTracker(config.account_config.grid_step_pct),
executor=executor
)
# 获取本策略的信号开仓数据
# 获取本策略的信号开仓数据
signals = init_signals(
config.global_config,
config.account_config.signal_allow,
)
log.info(
"[启动] Trend策略已启动账户=%s,信号=%d,持仓=%d",
config.account_config.account_id,
len(signals),
len(positions),
)
initialize = not state.state and not state.deals
deals = client.deals()
portfolio = client.portfolio()
if initialize and {d.order_sys_id: d for d in deals} != {
d.order_sys_id: d for d in client.deals()
}:
raise RuntimeError('ZT 初始化期间成交发生变化,请重新启动')
assets = portfolio.assets
positions = list(portfolio.positions.values())
log.info('[启动] ZT策略已启动账户=%s,信号=%d,持仓=%d',
config.account_config.account_id, len(signals), len(positions))
cache_portfolio(config.account_config.account_id, assets, positions, deals)
state.load()
state.sync_deals(deals)
state.sync_state(positions)
state.archiving()
state.sync_account(positions, deals, initialize=initialize)
run.orders.refresh(client, portfolio.orders)
Overview(assets, positions, config.account_config)
executor = ThreadPoolExecutor(max_workers=2, thread_name_prefix="zt")
DEFAULT_TICK_INTERVAL = 30
while True:
@@ -118,8 +112,7 @@ def RunOnce(run: Runtime, state: State, signals: list[SignalItem]) -> None:
positions = list(portfolio.positions.values())
position_codes = list(portfolio.positions)
state.sync_deals(deals)
state.archiving()
state.sync_account(positions, deals)
run.orders.refresh(run.client, portfolio.orders)
except Exception:
log.exception("[Portfolio] 刷新账户快照失败")
@@ -143,7 +136,7 @@ def RunOnce(run: Runtime, state: State, signals: list[SignalItem]) -> None:
allow_open: list[SignalItem] = []
allow_codes: list[str] = []
for signal in signals:
if signal.code not in portfolio.positions:
if signal.code not in portfolio.positions and signal.code not in state.blocked_codes:
allow_open.append(signal)
allow_codes.append(signal.code)

View File

@@ -1,6 +1,7 @@
"""趋势策略持仓止盈与分级补仓。"""
from dataclasses import dataclass
import math
from libs.calc import calc_buy_volume, calculate_min_profit_rate
from libs.grid_take_profit import GridState
@@ -45,9 +46,9 @@ def manage_positions(
continue
if (
not code
or position.open_price <= 0
or position.volume <= 0
or tick is None
or not math.isfinite(tick.last_price)
or tick.last_price <= 0
):
log.warning(
@@ -57,16 +58,24 @@ def manage_positions(
)
continue
if code in state.blocked_codes:
log.warning('[Position] %s 状态待核对,暂停该证券交易', code)
continue
posState = state.get_by_code(position.stock_code)
if not posState:
continue
volume = position.can_use_volume
target_qty = posState.get('base_qty', 0)
cost_price = position.open_price
if posState.get('added_qty',0) >=100:
volume = posState.get('added_qty',0)
if posState.get('added_qty', 0) > 0:
target_qty = posState['added_qty']
cost_price = posState.get('added_price',0)
# 在途股份不影响已有可卖库存;补仓、底仓均受柜台可卖上限约束。
volume = max(0, min(target_qty, position.can_use_volume, position.volume))
if not math.isfinite(cost_price) or cost_price <= 0:
log.warning('[Position] %s 成本无效,暂停该证券交易', code)
continue
pnl_rate = round(
(tick.last_price - cost_price) / cost_price * 100,
@@ -86,7 +95,8 @@ def manage_positions(
if runtime.account_cfg.enable_loss_add_position and market_ok:
loss_decision = handle_loss(
runtime=runtime,
position=position,
stock_code=position.stock_code,
volume=volume,
tick=tick,
pnl_rate=pnl_rate,
available=available,
@@ -99,7 +109,7 @@ def manage_positions(
strTag = "-"
if pnl_rate >= minimum_profit:
strTag = ""
elif pnl_rate< LOSS_TIERS[0]:
elif pnl_rate< LOSS_TIERS:
strTag = ""
if strTag != "-":
@@ -148,9 +158,8 @@ def handle_profit(
if runtime.orders.busy(stock_code, "SELL"):
return TradeDecision(False, "卖出委托处理中")
volume = volume % 100
if volume <= 0:
return TradeDecision(False, "无可用整手持仓")
return TradeDecision(False, "无可用持仓")
order_id = runtime.orders.new_order_id("zt","SELL")
request = PlaceOrderRequest(
op=OP_SELL,
@@ -199,7 +208,7 @@ def handle_loss(
if not runtime.orders.place(runtime.client, request):
return TradeDecision(False, "补仓订单委托失败")
runtime.add_watch.forget(position.stock_code)
runtime.add_watch.forget(stock_code)
return TradeDecision(True, f"[补仓买入] {volume} 股,订单={order_id}", amount)