fix bug
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -51,10 +51,11 @@ def StartTrend() -> None:
|
||||
config.global_config.qmt_token,
|
||||
config.HTTP_TIMEOUT,
|
||||
)
|
||||
assets = client.assets()
|
||||
_, positions = client.positions()
|
||||
portfolio = client.portfolio()
|
||||
assets = portfolio.assets
|
||||
positions = list(portfolio.positions.values())
|
||||
order_book = OrderBook()
|
||||
order_book.refresh(client)
|
||||
order_book.refresh(client, portfolio.orders)
|
||||
|
||||
storeState = State.for_strategy(
|
||||
config.global_config.qmt_data_dir,
|
||||
@@ -114,20 +115,18 @@ def RunOnce(run: Runtime, signals:list[SignalItem]) -> None:
|
||||
|
||||
started_at = time.monotonic()
|
||||
|
||||
# 1. 刷新订单数据,清理过期订单。
|
||||
# 1. 一次获取资产、持仓和订单,并清理过期订单。
|
||||
try:
|
||||
run.orders.refresh(run.client)
|
||||
portfolio = run.client.portfolio()
|
||||
assets = portfolio.assets
|
||||
position_codes = list(portfolio.positions)
|
||||
positions = list(portfolio.positions.values())
|
||||
run.orders.refresh(run.client, portfolio.orders)
|
||||
except Exception:
|
||||
log.exception("[Order] 刷新订单失败")
|
||||
log.exception("[Portfolio] 刷新账户快照失败")
|
||||
return
|
||||
|
||||
|
||||
# 2. 验证可用资金;低于资金安全线时禁止开新仓。
|
||||
try:
|
||||
assets = run.client.assets()
|
||||
except Exception:
|
||||
log.exception("[资金] 获取资产失败")
|
||||
return
|
||||
allow_open_by_cash = assets.available >= assets.total * run.account_cfg.min_cash_ratio
|
||||
if not allow_open_by_cash:
|
||||
log.info("[Status] 禁止开仓:可用资金不足,可用=%.2f,总资产=%.2f", assets.available, assets.total)
|
||||
@@ -135,14 +134,7 @@ def RunOnce(run: Runtime, signals:list[SignalItem]) -> None:
|
||||
# 3. 获取大盘状态,只有大盘信号允许时才执行开仓。
|
||||
market_ok = market_allow_open()
|
||||
|
||||
# 4. 获取当前持仓及持仓证券代码。
|
||||
try:
|
||||
position_codes, positions = run.client.positions()
|
||||
except Exception:
|
||||
log.exception("[Position] 获取持仓失败")
|
||||
return
|
||||
|
||||
# 5. 验证有效开仓信号:排除已有持仓和未决订单。
|
||||
# 4. 验证有效开仓信号:排除已有持仓和未决订单。
|
||||
allow_open: list[SignalItem] = []
|
||||
allow_codes: list[str] = []
|
||||
for signal in signals:
|
||||
@@ -153,7 +145,7 @@ def RunOnce(run: Runtime, signals:list[SignalItem]) -> None:
|
||||
if allow_open and not market_ok:
|
||||
log.info("[开仓] 禁止开仓:大盘信号不允许,候选=%d", len(allow_open))
|
||||
|
||||
# 6. 获取持仓和待开仓证券的实时行情 tick。
|
||||
# 5. 获取持仓和待开仓证券的实时行情 tick。
|
||||
all_codes = list(dict.fromkeys(position_codes + allow_codes))
|
||||
try:
|
||||
ticks = run.client.full_tick(all_codes)
|
||||
@@ -161,7 +153,7 @@ def RunOnce(run: Runtime, signals:list[SignalItem]) -> None:
|
||||
log.exception("[行情] 获取行情失败,代码数量=%d", len(all_codes))
|
||||
return
|
||||
|
||||
# 7. 更新状态机
|
||||
# 6. 更新状态机
|
||||
try:
|
||||
run.state.reconcile(positions, run.orders.data)
|
||||
except Exception:
|
||||
@@ -171,7 +163,7 @@ def RunOnce(run: Runtime, signals:list[SignalItem]) -> None:
|
||||
log.info("[RunOnce] 本轮就绪,持仓=%d,候选=%d,大盘允许=%s,资金允许=%s", len(positions), len(allow_open), market_ok, allow_open_by_cash)
|
||||
|
||||
# 启动线程,开始计算
|
||||
# 9. 持仓计算。
|
||||
# 7. 持仓计算。
|
||||
futures: list[tuple[str, Future]] = [
|
||||
(
|
||||
"持仓计算",
|
||||
@@ -186,11 +178,11 @@ def RunOnce(run: Runtime, signals:list[SignalItem]) -> None:
|
||||
)
|
||||
]
|
||||
|
||||
# 10. 开仓计算:必须同时存在有效信号且大盘允许开仓。
|
||||
# 8. 开仓计算:必须同时存在有效信号且大盘允许开仓。
|
||||
if allow_open and market_ok and allow_open_by_cash:
|
||||
futures.append(("开仓计算", run.executor.submit(open_signal, run, ticks, allow_open)))
|
||||
|
||||
# 11. 开始执行
|
||||
# 9. 开始执行
|
||||
for name, future in futures:
|
||||
_wait_worker(name, future)
|
||||
log.info("[RunOnce] 本轮完成,耗时=%d毫秒", int((time.monotonic() - started_at) * 1000))
|
||||
|
||||
@@ -71,7 +71,6 @@ def do_open(run:Runtime,code:str,volume:int,signal_key:str)->None:
|
||||
run.client,
|
||||
OP_BUY,
|
||||
code,
|
||||
-1,
|
||||
volume,
|
||||
order_id,
|
||||
signal_key,
|
||||
|
||||
@@ -25,7 +25,6 @@ class PlaceOrderRequest:
|
||||
client: Any
|
||||
op: int
|
||||
code: str
|
||||
price: float
|
||||
volume: int
|
||||
order_id: str
|
||||
strategy_name: str
|
||||
@@ -52,9 +51,8 @@ class OrderBook:
|
||||
key = f"{side}-{code}"
|
||||
return key in self.lock
|
||||
|
||||
def refresh(self, client: Client) -> None:
|
||||
"""从 QMT 刷新进行中和已完成委托,并撤销超时的活动委托。"""
|
||||
orders = client.trade_detail_data("order")
|
||||
def refresh(self, client: Client, orders: list[OrderItem]) -> None:
|
||||
"""用账户快照刷新委托,并撤销超时的活动委托。"""
|
||||
current = datetime.now()
|
||||
now_timestamp = current.timestamp()
|
||||
data: list[OrderItem] = []
|
||||
|
||||
@@ -47,7 +47,7 @@ def manage_positions(
|
||||
code = position.stock_code
|
||||
tick = ticks.get(code)
|
||||
if code in runtime.account_cfg.excluded_codes:
|
||||
log.info("[Position] %s %s 止盈=跳过,补仓=跳过,原因=已配置为排除股票", code, position.stock_name)
|
||||
log.info("[Position] 代码=%s,名称=%s,止盈=跳过,补仓=跳过,原因=已配置为排除股票", code, position.stock_name)
|
||||
continue
|
||||
if (
|
||||
not code
|
||||
@@ -56,7 +56,7 @@ def manage_positions(
|
||||
or tick is None
|
||||
or tick.last_price <= 0
|
||||
):
|
||||
log.warning("[Position] %s %s 止盈=跳过,补仓=跳过,原因=持仓或行情数据无效", code or "未知", position.stock_name)
|
||||
log.warning("[Position] 代码=%s,名称=%s,止盈=跳过,补仓=跳过,原因=持仓或行情数据无效", code or "未知", position.stock_name)
|
||||
continue
|
||||
|
||||
pnl_rate = round(
|
||||
@@ -87,7 +87,7 @@ def manage_positions(
|
||||
loss_add_action = "大盘信号不允许"
|
||||
|
||||
log.info(
|
||||
"[Position] %s %s 盈亏=%.2f%%,止盈=%s,补仓=%s",
|
||||
"[Position] 代码=%s,名称=%s,盈亏=%.2f%%,止盈=%s,补仓=%s",
|
||||
code, position.stock_name, pnl_rate, profit_action, loss_add_action,
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user