Show auto-close as off when partial manual-complete is enabled.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -141,8 +141,8 @@ HEDGE_PLAN_OPTIONS_MUTUAL_EXCLUSIVE=true
|
|||||||
HEDGE_PLAN_MANUAL_COMPLETE_ON_PARTIAL=true
|
HEDGE_PLAN_MANUAL_COMPLETE_ON_PARTIAL=true
|
||||||
MAX_ACTIVE_HEDGE_PLANS=1
|
MAX_ACTIVE_HEDGE_PLANS=1
|
||||||
HEDGE_PLAN_MONITOR_POLL_SECONDS=15
|
HEDGE_PLAN_MONITOR_POLL_SECONDS=15
|
||||||
# 半腿失败自动平期权;若 MANUAL_COMPLETE_ON_PARTIAL=true 则不会执行自动平
|
# 半腿失败自动平期权;若 MANUAL_COMPLETE_ON_PARTIAL=true 则运行时强制无效(建议一并写成 false)
|
||||||
HEDGE_PLAN_PARTIAL_AUTO_CLOSE_OPTION=true
|
HEDGE_PLAN_PARTIAL_AUTO_CLOSE_OPTION=false
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# 关键位程序自动下单(与 POSITION_SIZING_MODE 联动,修改后须重启 PM2)
|
# 关键位程序自动下单(与 POSITION_SIZING_MODE 联动,修改后须重启 PM2)
|
||||||
|
|||||||
Vendored
+34
@@ -193,6 +193,10 @@ def _effective_env_value(key: str, file_values: dict[str, str], schema_default:
|
|||||||
return _RUNTIME_ENV_DEFAULTS.get(key, "")
|
return _RUNTIME_ENV_DEFAULTS.get(key, "")
|
||||||
|
|
||||||
|
|
||||||
|
def _env_truthy(raw: str) -> bool:
|
||||||
|
return str(raw or "").strip().lower() in ("1", "true", "yes", "on")
|
||||||
|
|
||||||
|
|
||||||
def _schema_field_map(example_path: str) -> dict[str, dict[str, Any]]:
|
def _schema_field_map(example_path: str) -> dict[str, dict[str, Any]]:
|
||||||
out: dict[str, dict[str, Any]] = {}
|
out: dict[str, dict[str, Any]] = {}
|
||||||
for group in parse_env_example_schema(example_path):
|
for group in parse_env_example_schema(example_path):
|
||||||
@@ -211,6 +215,13 @@ def _build_field(
|
|||||||
meta = schema.get(key) or {}
|
meta = schema.get(key) or {}
|
||||||
schema_default = meta.get("default") or ""
|
schema_default = meta.get("default") or ""
|
||||||
val = _effective_env_value(key, values, schema_default)
|
val = _effective_env_value(key, values, schema_default)
|
||||||
|
# 与运行时一致:手动补开开启时,「自动平期权」展示为关闭(实际也不会执行)
|
||||||
|
if key == "HEDGE_PLAN_PARTIAL_AUTO_CLOSE_OPTION":
|
||||||
|
manual = _effective_env_value(
|
||||||
|
"HEDGE_PLAN_MANUAL_COMPLETE_ON_PARTIAL", values, "true"
|
||||||
|
)
|
||||||
|
if _env_truthy(manual):
|
||||||
|
val = "false"
|
||||||
masked = _mask_value(key, val)
|
masked = _mask_value(key, val)
|
||||||
ftype = meta.get("type") or _field_type(key, val or schema_default)
|
ftype = meta.get("type") or _field_type(key, val or schema_default)
|
||||||
options = select_options_for(key)
|
options = select_options_for(key)
|
||||||
@@ -322,3 +333,26 @@ def validate_env_ui_updates(
|
|||||||
)
|
)
|
||||||
groups.append({"title": sec["title"], "fields": fields})
|
groups.append({"title": sec["title"], "fields": fields})
|
||||||
return validate_env_updates(groups, updates)
|
return validate_env_updates(groups, updates)
|
||||||
|
|
||||||
|
|
||||||
|
def coerce_hedge_partial_close_with_manual(
|
||||||
|
clean: dict[str, str],
|
||||||
|
*,
|
||||||
|
env_path: str = "",
|
||||||
|
) -> dict[str, str]:
|
||||||
|
"""手动补开为开启时,强制把自动平写成 false(与运行时一致)."""
|
||||||
|
out = dict(clean or {})
|
||||||
|
manual = out.get("HEDGE_PLAN_MANUAL_COMPLETE_ON_PARTIAL")
|
||||||
|
if manual is None and env_path:
|
||||||
|
try:
|
||||||
|
from lib.env.env_file_lib import env_get_all, read_env_lines
|
||||||
|
|
||||||
|
file_vals = env_get_all(read_env_lines(env_path))
|
||||||
|
manual = _effective_env_value(
|
||||||
|
"HEDGE_PLAN_MANUAL_COMPLETE_ON_PARTIAL", file_vals, "true"
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
manual = "true"
|
||||||
|
if _env_truthy(str(manual or "")):
|
||||||
|
out["HEDGE_PLAN_PARTIAL_AUTO_CLOSE_OPTION"] = "false"
|
||||||
|
return out
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ from lib.env.env_file_lib import apply_env_updates, env_get, read_env_lines
|
|||||||
from lib.env.env_ui_manifest import (
|
from lib.env.env_ui_manifest import (
|
||||||
build_env_ui_payload,
|
build_env_ui_payload,
|
||||||
filter_updates_for_ui,
|
filter_updates_for_ui,
|
||||||
|
coerce_hedge_partial_close_with_manual,
|
||||||
validate_env_ui_updates,
|
validate_env_ui_updates,
|
||||||
)
|
)
|
||||||
from lib.env.env_schema import parse_env_example_schema
|
from lib.env.env_schema import parse_env_example_schema
|
||||||
@@ -102,6 +103,7 @@ def register_instance_settings_routes(
|
|||||||
clean, errors = validate_env_ui_updates(exchange_key, example_path, updates)
|
clean, errors = validate_env_ui_updates(exchange_key, example_path, updates)
|
||||||
if errors:
|
if errors:
|
||||||
return jsonify({"ok": False, "msg": "; ".join(errors)}), 400
|
return jsonify({"ok": False, "msg": "; ".join(errors)}), 400
|
||||||
|
clean = coerce_hedge_partial_close_with_manual(clean, env_path=env_path)
|
||||||
if not clean:
|
if not clean:
|
||||||
return jsonify({"ok": True, "changed_keys": [], "restart_required": False})
|
return jsonify({"ok": True, "changed_keys": [], "restart_required": False})
|
||||||
changed = apply_env_updates(env_path, clean)
|
changed = apply_env_updates(env_path, clean)
|
||||||
|
|||||||
Reference in New Issue
Block a user