From 66ccd42d4edd077584329036b2d128e1b7fddd26 Mon Sep 17 00:00:00 2001 From: yanweidong Date: Tue, 1 Sep 2026 15:49:09 +0800 Subject: [PATCH] fix bug --- .../trend/__pycache__/boot.cpython-311.pyc | Bin 10362 -> 10362 bytes .../trend/__pycache__/open.cpython-311.pyc | Bin 6937 -> 6903 bytes .../trend/__pycache__/order.cpython-311.pyc | Bin 8229 -> 8219 bytes .../__pycache__/positions.cpython-311.pyc | Bin 9421 -> 9357 bytes .../trend/__pycache__/watch.cpython-311.pyc | Bin 5091 -> 5037 bytes py-client/strategy/trend/boot.py | 8 +++---- py-client/strategy/trend/open.py | 22 +++++++++--------- py-client/strategy/trend/order.py | 12 +++++----- py-client/strategy/trend/positions.py | 6 ++--- py-client/strategy/trend/watch.py | 15 ++++++------ 10 files changed, 31 insertions(+), 32 deletions(-) diff --git a/py-client/strategy/trend/__pycache__/boot.cpython-311.pyc b/py-client/strategy/trend/__pycache__/boot.cpython-311.pyc index be15688b95e1dc9a48eed646a4d46063503d8148..ff2af621c90c1b1e7f9afea6b6fc8ef488e3d4f8 100644 GIT binary patch delta 164 zcmewr@GF38IWI340|Ns?L-9r~ZD|e;g^;izhFXcIK4@$pqvVXO?8<=WTv3?ZIs9zm#JM&qBT>eAgAsFDaN`u<*X9;B!U6 z=Yps|1YP9vzYrLCkt^~dOVkyXs0%Dnle6UAxr{Dy7+>KqzQAETdAIx%F4Kz~W>+}O NE^wG_Ua4@A9RS1JH~0Vm delta 150 zcmewr@GF38IWI340|Ns?RQ^UTZD~$Ug`m zDZnY|k8QMjtQOqAU4PUl6D&|H02ZWi?ERlz!Iv0Os$zFJ3NeAk5|GT$WD!bF2)|1C zRnVo%jzI-6+%jXN%sXCMp>Lvoq2Yyal!g4GZ2c<&@2e^R1hKenBWq{CBP+uOR8+|R}jM% zv^6J`vHkfZILGTfjXr&N9u^iMnr7@5u8>`+L)@UN{rENtY3Poa^@;_XvHCs z@F;p%71Wbp(Tie@AlQN)JmiqWADDxey){KoZlK~GWmno}QFy%J{l|ZA;QtOh9pYYb z++KtbI*@&mdB4h4Y(6(aDAruBZmh|1&&KB$&4(X1t81H&-~C*F)|y^j5CaCcS< zITU7K+JaCOHLbRL=Yi{c<9~gZ_(rL3lvsn*8U$V2F6jzTPAsRu0e;?6E;^3$` ziSPx=7hoHzh2cbbj_YS~@&nFOxdO9MIy(o#JQYM(zD=-1u>@EmSke^dVHGisl3ugJ z3U=PV2;GzQGmT+mc^+;qL1CHTBE>~8gW#g^UuU--ku!p}Sq}fq9lcYKH|BLJY!m2>&B zljbAJa1-4t-h**X=vk@fM8S{+Q^gNWU`^iT^!1QWk!V&&auwZK8V-J!7oPiM6lh z4Y7M5cPk!1jZI*KVirAs6skliTqDZh22lpL1G4Y~U=NE#B|OA8B8wD?Hvn!EaGL~f zI}h!Hom;{vNy8SElLkPQC44REYe`>AIs>u%@}4klY1TY|V>U&%$1F|PDlXv{#VWoB z;Q{ElNo`cjkxAhJ6wvg07yaJ;A9>OBVj(tN7KgP4fW^j1oWvQ5L@;Usmx(l7r#dYd lbtf1uz1U&5SnP*MBT+D67VF5 zAS`Sp9x={`Kg@UEr_Omp%4Q_$a1zVU(m%7L}T;n4)RP=58n9$b=&jj(gYl z`B~vcTN1C|bTnOR`i)T(rL~Sx4ofyWaZ|=k@vyxwiLsbk=zZZNWQESSY?E^S$lIk3m z3q$f@NIne7yH5wp%XMMe(rozvZ8l4+3U%>oR^o2fq{YHe95#di;cW$oT32?3=Gi$`Nf$fnfZCK3aZ5*G&zFPO*9yX zjQZqPoSQ|>u*q&d#I=W!(P(l#&lLIe3z@kW^2@(4FcdI4Gks)W;B{g80wzCz$jN5B w4w|_a@{2Fz*Iy{F|G>cD#N-81;KURPRviXb9R^k%HhDGgYetvN)A`KA080xzH2?qr delta 264 zcmeD6JnPB3oR^o2fq{YHMB22hjE%f%oT>>73=GlFdK#bXo*b+2WcT9d3mR=zi{J0* zc{-u@`SJ}A_GAxEH`Qb!RjN-u#kpD4jTqINCvojzWOSPB&of22{6b~z2L=WQCJ&}B zAS#&YBLf3(2#CWQ!t?<|PG;hDFoh^`0f{&;1%N0I2o=N>1yUTulnU0F2G*Gd)|oar OoA)(i$mVc9Gcf>RhGlC2 diff --git a/py-client/strategy/trend/__pycache__/watch.cpython-311.pyc b/py-client/strategy/trend/__pycache__/watch.cpython-311.pyc index 0db6c9af0ab0cdc8063487758969df70c59d556e..c2f420f251bf030e545ca5e24990aae691eab567 100644 GIT binary patch delta 935 zcma)3OK4L;6ur}AUfwS+ACo4P3aJ=^Mk>#y#%gQ~%EN^S;wP0FMH{4vAd<9*;Yqs@ z%%U5|PjD67xDwQgEi@}X*|Mn2HHPRHY!`TAta8d>` zc=u3GC&}W1w+SJ^+cJRm!EW+U3Z9Htu3W8LyID!5s`hlvp03!_bqE;kPkQ5QaXoIT; zErmWQ*%@jvpomBX6|*Q+>c&L^U1TE&I-)CIpo`*4X3|t!TF7HK_uO;Oxy&%{Mc`XN zE;<|{06_WrT+-)wC110lDRSHP8u#l^;7AC!ksEBc7wbrG(HR|*g6THTQw;DNlY2Ob zMDh$zw@VuXNLeI(PG^%68Dw+8%}GWCFx7@LBLQ6DGZ^45uk+^iS?;K7bF4FUk@Rt6 zNFoc|Jo~eF-+1|$4DvoT1^}1*6Llrg>7VE{N?D`$fGqKz1HVfTjhShq^zK)F%E*>_ z{oTi|`u(?h|Id&o{OQI*gV!1~B*YtZMz|w+0U&L@Qd%T!Vir}%Bk?TTBd8R5$QLnu zVYuq{RNZRT?X9}iRd-iSVqMA_ur7sKAcMM>dg}ozC8#y%5!5vk=r-seBT}$0UcQ(p zkB*hclND!b)tM?gQ&mp~-M=NU`;vp?lQeWF(xf{|2JDHhA=IQjPCnaDPNtf*Z~H#8 zU0+|{N&crz90q_=Owq#3vhS1@W-bv~f%3TptQwJfwMl(Q%g&UPwTR0MfX-j*AslGWNll&Qm_R(uPdZ^2kY`QsGKS~yX!JK*9G WC5Fz7AS6=Q8Ecllw#ziF0Ki}S9u#H( diff --git a/py-client/strategy/trend/boot.py b/py-client/strategy/trend/boot.py index aa5b2d2..bc3df77 100644 --- a/py-client/strategy/trend/boot.py +++ b/py-client/strategy/trend/boot.py @@ -111,7 +111,7 @@ def RunOnce(run: Runtime, signals:list[SignalItem]) -> None: log.info("[运行] 非交易时间,跳过本轮") return - print("=" * 40 + f" RunOnce {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} " +"=" * 40) + print("=" * 40 + f" Ticker {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} " +"=" * 40) started_at = time.monotonic() @@ -119,7 +119,7 @@ def RunOnce(run: Runtime, signals:list[SignalItem]) -> None: try: run.orders.refresh(run.client) except Exception: - log.exception("[订单] 刷新订单失败") + log.exception("[Order] 刷新订单失败") return @@ -131,7 +131,7 @@ def RunOnce(run: Runtime, signals:list[SignalItem]) -> None: return allow_open_by_cash = assets.available >= assets.total * run.account_cfg.min_cash_ratio if not allow_open_by_cash: - log.info("[开仓] 禁止开仓:可用资金不足,可用=%.2f,总资产=%.2f", assets.available, assets.total) + log.info("[Status] 禁止开仓:可用资金不足,可用=%.2f,总资产=%.2f", assets.available, assets.total) # 3. 获取大盘状态,只有大盘信号允许时才执行开仓。 market_ok = market_allow_open() @@ -140,7 +140,7 @@ def RunOnce(run: Runtime, signals:list[SignalItem]) -> None: try: position_codes, positions = run.client.positions() except Exception: - log.exception("[持仓] 获取持仓失败") + log.exception("[Position] 获取持仓失败") return # 5. 验证有效开仓信号:排除已有持仓和未决订单。 diff --git a/py-client/strategy/trend/open.py b/py-client/strategy/trend/open.py index 9592fb9..bfbdddb 100644 --- a/py-client/strategy/trend/open.py +++ b/py-client/strategy/trend/open.py @@ -14,41 +14,41 @@ import logging as log def open_signal(run:Runtime, ticks, open_signals) -> None: """逐个验证开仓信号并提交买入委托。""" - log.info("[开仓] 信号总数:%d", len(open_signals)) + log.info("[Open] 信号总数:%d", len(open_signals)) for item in open_signals: # 1. 验证信号配置允许开仓的时间区间。 signal_config = run.global_cfg.signals.get(item.signal_key) if signal_config is None or not check_timezone(signal_config.timezone): - log.info("[开仓] %s 信号=%s,跳过:不在信号时间段(%s)", item.code, item.signal_key,signal_config.timezone) + log.info("[Open] %s 信号=%s,跳过:不在信号时间段(%s)", item.code, item.signal_key,signal_config.timezone) continue # 2. 检查该证券是否已有买入委托锁,防止重复下单。 if run.orders.busy(item.code,"BUY"): - log.info("[开仓] %s 信号=%s,跳过:买入委托处理中", item.code, item.signal_key) + log.info("[Open] %s 信号=%s,跳过:买入委托处理中", item.code, item.signal_key) continue # 3. 验证行情和最新价格是否有效。 tick = ticks.get(item.code) price = tick.last_price if tick is not None else 0 if price <= 0: - log.info("[开仓] %s 信号=%s,跳过:价格无效", item.code, item.signal_key) + log.info("[Open] %s 信号=%s,跳过:价格无效", item.code, item.signal_key) continue # 5. 根据单笔买入金额计算整手开仓数量。 volume = calc_buy_volume(price, run.account_cfg.buy_value) if volume <= 0: - log.info("[开仓] %s 信号=%s,跳过:数量无效", item.code, item.signal_key) + log.info("[Open] %s 信号=%s,跳过:数量无效", item.code, item.signal_key) continue # 当前价高于昨收价可开仓 if signal_config.gt_last_price_is_open and item.last_close>0 and price>item.last_close: try: do_open(run,item.code,volume,item.signal_key) - log.info("[开仓] %s 信号=%s,买入=%d股,原因=现价高于昨收", item.code, item.signal_key, volume) + log.info("[Open] %s 信号=%s,买入=%d股,原因=现价高于昨收", item.code, item.signal_key, volume) except RuntimeError as exc: - log.info("[开仓] %s 信号=%s,买入=%d股失败:%s", item.code, item.signal_key, volume, exc) + log.info("[Open] %s 信号=%s,买入=%d股失败:%s", item.code, item.signal_key, volume, exc) except Exception: - log.exception("[开仓] %s 信号=%s,买入=%d股异常", item.code, item.signal_key, volume) + log.exception("[Open] %s 信号=%s,买入=%d股异常", item.code, item.signal_key, volume) continue # 4. 等待价格从观察低点反弹,防止直接接下跌中的“飞刀”。 @@ -57,11 +57,11 @@ def open_signal(run:Runtime, ticks, open_signals) -> None: try: do_open(run,item.code,volume,item.signal_key) - log.info("[开仓] %s 信号=%s,买入=%d股,原因=反弹已确认", item.code, item.signal_key, volume) + log.info("[Open] %s 信号=%s,买入=%d股,原因=反弹已确认", item.code, item.signal_key, volume) except RuntimeError as exc: - log.warning("[开仓] %s 信号=%s,买入=%d股失败:%s", item.code, item.signal_key, volume, exc) + log.warning("[Open] %s 信号=%s,买入=%d股失败:%s", item.code, item.signal_key, volume, exc) except Exception: - log.exception("[开仓] %s 信号=%s,买入=%d股异常", item.code, item.signal_key, volume) + log.exception("[Open] %s 信号=%s,买入=%d股异常", item.code, item.signal_key, volume) def do_open(run:Runtime,code:str,volume:int,signal_key:str)->None: diff --git a/py-client/strategy/trend/order.py b/py-client/strategy/trend/order.py index 5aadf06..59fc0db 100644 --- a/py-client/strategy/trend/order.py +++ b/py-client/strategy/trend/order.py @@ -72,7 +72,7 @@ class OrderBook: ): client.cancel_by_id(item.id) canceled += 1 - log.info("[订单] 超时撤单,代码=%s,方向=%s,柜台订单=%s", item.code, item.side, item.id) + log.info("[Order] 超时撤单,代码=%s,方向=%s,柜台订单=%s", item.code, item.side, item.id) continue # 缓存本次有效订单 @@ -90,7 +90,7 @@ class OrderBook: with self.mutex: self.data = data self.lock = lock - log.info("[订单] 刷新完成,跟踪=%d,处理中=%d,撤销=%d", len(data), len(lock), canceled) + log.info("[Order] 刷新完成,跟踪=%d,处理中=%d,撤销=%d", len(data), len(lock), canceled) def place(self, request: PlaceOrderRequest) -> bool: """按最新价提交委托,并立即写入本地方向锁。""" @@ -103,14 +103,14 @@ class OrderBook: request.order_id, ) except APIError as exc: - log.exception("[订单] 下单失败,代码=%s,本地订单=%s,HTTP状态=%d,错误=%s", request.code, request.order_id, exc.status_code, exc.message or str(exc)) + log.exception("[Order] 下单失败,代码=%s,本地订单=%s,HTTP状态=%d,错误=%s", request.code, request.order_id, exc.status_code, exc.message or str(exc)) return False if not isinstance(result, dict): - log.warning("[订单] 下单失败,代码=%s,本地订单=%s,原因=响应格式无效", request.code, request.order_id) + log.warning("[Order] 下单失败,代码=%s,本地订单=%s,原因=响应格式无效", request.code, request.order_id) return False order_ref = str(result.get("order_ref") or "").strip().lower() if result.get("status") != "success" or order_ref in {"", "unknown", "none"}: - log.warning("[订单] 下单被拒绝,代码=%s,本地订单=%s,状态=%s,柜台订单=%s", request.code, request.order_id, result.get("status"), order_ref) + log.warning("[Order] 下单被拒绝,代码=%s,本地订单=%s,状态=%s,柜台订单=%s", request.code, request.order_id, result.get("status"), order_ref) return False side = ORDER_SIDE_BY_OFFSET.get(str(request.op), "") @@ -128,5 +128,5 @@ class OrderBook: key = f"{side}-{request.code}" self.data.append(pending) self.lock[key] = pending.created_at.timestamp() - log.info("[订单] 下单已受理,代码=%s,方向=%s,数量=%d,本地订单=%s,柜台订单=%s", request.code, side, request.volume, request.order_id, order_ref) + log.info("[Order] 下单已受理,代码=%s,方向=%s,数量=%d,本地订单=%s,柜台订单=%s", request.code, side, request.volume, request.order_id, order_ref) return True diff --git a/py-client/strategy/trend/positions.py b/py-client/strategy/trend/positions.py index bc2fe84..6bee0a3 100644 --- a/py-client/strategy/trend/positions.py +++ b/py-client/strategy/trend/positions.py @@ -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("[持仓] 代码=%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("[持仓] 代码=%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( - "[持仓] 代码=%s,名称=%s,盈亏=%.2f%%,止盈=%s,补仓=%s", + "[Position] %s %s 盈亏=%.2f%%,止盈=%s,补仓=%s", code, position.stock_name, pnl_rate, profit_action, loss_add_action, ) diff --git a/py-client/strategy/trend/watch.py b/py-client/strategy/trend/watch.py index 315fb19..16372b1 100644 --- a/py-client/strategy/trend/watch.py +++ b/py-client/strategy/trend/watch.py @@ -32,7 +32,7 @@ class DipWatch: ) -> bool: """更新观察价格;达到反弹阈值时返回 ``True``。""" if price <= 0: - log.warning("[%s观察] %s 价格无效:%.2f", tag, code, price) + log.warning("[%s Watch] %s 价格无效:%.2f", tag, code, price) return False current = now or datetime.now() @@ -42,24 +42,23 @@ class DipWatch: if watch is None: self._start(code, price, current) log.info( - "[%s观察] %s 开始观察,收盘价=%.2f,反弹阈值=%.2f%%", + "[%s Watch] %s 开始观察,收盘价=%.2f", tag, code, price, - self.rebound_threshold, ) return False if current >= watch.expires_at: self._start(code, price, current) - log.info("[%s观察] %s 观察已过期,重新观察,收盘价=%.2f", tag, code, price) + log.info("[%sWatch] %s 观察已过期,重新观察,收盘价=%.2f", tag, code, price) return False if price < watch.last_close: old_price = watch.last_close self._start(code, price, current) log.info( - "[%s观察] %s 刷新低点,原收盘价=%.2f,新收盘价=%.2f", + "[%s Watch] %s 刷新低点,原收盘价=%.2f,新收盘价=%.2f", tag, code, old_price, @@ -70,7 +69,7 @@ class DipWatch: rebound = (price - watch.last_close) / watch.last_close * 100 if rebound < self.rebound_threshold: log.debug( - "[%s观察] %s 等待反弹,收盘价=%.2f,现价=%.2f,反弹=%.2f%%,阈值=%.2f%%", + "[%s Watch] %s 等待反弹,收盘价=%.2f,现价=%.2f,反弹=%.2f%%,阈值=%.2f%%", tag, code, watch.last_close, @@ -82,7 +81,7 @@ class DipWatch: del self.data[code] log.info( - "[%s观察] %s 反弹触发,收盘价=%.2f,现价=%.2f,反弹=%.2f%%", + "[%s Watch] %s 反弹触发,收盘价=%.2f,现价=%.2f,反弹=%.2f%%", tag, code, watch.last_close, @@ -96,7 +95,7 @@ class DipWatch: with self.lock: removed = self.data.pop(code, None) if removed is not None: - log.info("[价格观察] %s 已清除观察状态", code) + log.info("[Watch] %s 已清除观察状态", code) def _start(self, code: str, price: float, now: datetime) -> None: self.data[code] = _Entry(