Floor ATR at 10 USD for SL/TP when ATR mode enabled.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-10-21 10:23:16 +08:00
parent 60ecc65f1c
commit c436b76e64
2 changed files with 14 additions and 6 deletions
+14 -6
View File
@@ -39,6 +39,7 @@ DEFAULT_TP_USD = 12.0
DEFAULT_PARTIAL = 0.10 DEFAULT_PARTIAL = 0.10
ATR_PERIOD = 14 ATR_PERIOD = 14
ATR_TIMEFRAME = None ATR_TIMEFRAME = None
ATR_FLOOR_USD = 10.0 # ATR 低于该值时,止损/止盈按 10 美金计;高于则用实际 ATR
MAGIC = 20261016 MAGIC = 20261016
COMMENT = "GoldPanel" COMMENT = "GoldPanel"
DEVIATION = 100 DEVIATION = 100
@@ -1110,7 +1111,7 @@ class OrderApp(tk.Tk):
self.var_use_atr = tk.BooleanVar(value=True) self.var_use_atr = tk.BooleanVar(value=True)
ttk.Checkbutton( ttk.Checkbutton(
opt, opt,
text="用 M15 ATR(14) 做止损/止盈", text="用 M15 ATR(14) 做止损/止盈(ATR<10 按 10)",
variable=self.var_use_atr, variable=self.var_use_atr,
command=self._sync_sl_label, command=self._sync_sl_label,
).pack(side=tk.LEFT) ).pack(side=tk.LEFT)
@@ -1292,8 +1293,13 @@ class OrderApp(tk.Tk):
except ValueError as exc: except ValueError as exc:
raise TradeError(f"{name} 不是有效数字") from exc raise TradeError(f"{name} 不是有效数字") from exc
@staticmethod
def _atr_for_stops(atr: float) -> float:
"""止损/止盈用的 ATR:小于 10 按 10,大于等于 10 用实际值。"""
return max(float(atr), ATR_FLOOR_USD)
def _resolve_stops(self, symbol: str) -> Tuple[float, float, float, float, float]: def _resolve_stops(self, symbol: str) -> Tuple[float, float, float, float, float]:
"""返回 sl_usd, tp_usd, atr, sl_mult, tp_mult""" """返回 sl_usd, tp_usd, atr(原始), sl_mult, tp_mult"""
if not self.var_use_atr.get(): if not self.var_use_atr.get():
sl = self._parse_float(self.var_atr_mult.get(), "SL$") sl = self._parse_float(self.var_atr_mult.get(), "SL$")
tp = self._parse_float(self.var_tp.get(), "TP$") tp = self._parse_float(self.var_tp.get(), "TP$")
@@ -1304,7 +1310,8 @@ class OrderApp(tk.Tk):
if sl_mult < 0 or tp_mult < 0: if sl_mult < 0 or tp_mult < 0:
raise TradeError("ATR 倍数不能为负") raise TradeError("ATR 倍数不能为负")
atr = self.bridge.atr(symbol) if (sl_mult > 1e-8 or tp_mult > 1e-8) else 0.0 atr = self.bridge.atr(symbol) if (sl_mult > 1e-8 or tp_mult > 1e-8) else 0.0
return atr * sl_mult, atr * tp_mult, atr, sl_mult, tp_mult base = self._atr_for_stops(atr) if atr > 1e-12 else 0.0
return base * sl_mult, base * tp_mult, atr, sl_mult, tp_mult
def _confirm(self, title: str, body: str) -> bool: def _confirm(self, title: str, body: str) -> bool:
if not MUST_CONFIRM: if not MUST_CONFIRM:
@@ -1752,11 +1759,12 @@ class OrderApp(tk.Tk):
if self.var_use_atr.get(): if self.var_use_atr.get():
try: try:
atr = self.bridge.atr(symbol) atr = self.bridge.atr(symbol)
atr_txt = f"{atr:.2f}" base = self._atr_for_stops(atr)
atr_txt = f"{atr:.2f}" + (f"→{base:.0f}" if base > atr + 1e-9 else "")
sl_m = float(self.var_atr_mult.get().replace(",", ".") or "0") sl_m = float(self.var_atr_mult.get().replace(",", ".") or "0")
tp_m = float(self.var_tp.get().replace(",", ".") or "0") tp_m = float(self.var_tp.get().replace(",", ".") or "0")
sl_txt = f"{atr * sl_m:.2f}" sl_txt = f"{base * sl_m:.2f}"
tp_txt = f"{atr * tp_m:.2f}" tp_txt = f"{base * tp_m:.2f}"
except Exception: except Exception:
pass pass
else: else:
Binary file not shown.