User edition: prune docs, license gate, obfuscate core lib.

Keep deploy/basic docs only; integrate sq.bz121.com license client; encrypt strategy/trade/key_monitor/options/hedge_plan for release.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-17 16:30:58 +08:00
parent 53863559f4
commit 16ef0f31e3
154 changed files with 1998 additions and 27914 deletions
+12 -143
View File
@@ -1,143 +1,12 @@
"""策略交易页:主站 index.html 所需数据(顺势加仓等)."""
from __future__ import annotations
from typing import Any, Callable, Optional
from lib.strategy.strategy_db import init_strategy_tables
from lib.strategy.strategy_roll_monitor_lib import roll_leg_status_label
def _row_to_dict(row) -> dict:
if row is None:
return {}
try:
return dict(row)
except Exception:
return {}
def count_active_trend_plans(conn, count_fn: Optional[Callable] = None) -> int:
if callable(count_fn):
return int(count_fn(conn) or 0)
try:
return int(
conn.execute(
"SELECT COUNT(*) FROM trend_pullback_plans WHERE status='active'"
).fetchone()[0]
)
except Exception:
return 0
def fetch_roll_page_data(
conn,
*,
default_risk_percent: float = 2.0,
count_active_trends: Optional[Callable] = None,
roll_cfg: dict | None = None,
) -> dict[str, Any]:
init_strategy_tables(conn)
monitors = []
for row in conn.execute(
"SELECT * FROM order_monitors WHERE status='active' ORDER BY id DESC"
).fetchall():
monitors.append(_row_to_dict(row))
roll_groups = []
for row in conn.execute(
"""SELECT g.* FROM roll_groups g
INNER JOIN order_monitors m ON m.id = g.order_monitor_id AND m.status='active'
WHERE g.status='active'
ORDER BY g.id DESC"""
).fetchall():
roll_groups.append(_row_to_dict(row))
active_gids = {int(g["id"]) for g in roll_groups if g.get("id") is not None}
roll_legs = []
for row in conn.execute(
"SELECT * FROM roll_legs ORDER BY id DESC LIMIT 80"
).fetchall():
leg = _row_to_dict(row)
gid = leg.get("roll_group_id")
if gid is not None and int(gid) not in active_gids:
continue
leg["status_label"] = roll_leg_status_label(leg.get("status"))
roll_legs.append(leg)
roll_legs = roll_legs[:50]
out = {
"roll_monitors": monitors,
"roll_groups": roll_groups,
"roll_legs": roll_legs,
"roll_trend_active": count_active_trend_plans(conn, count_active_trends),
"default_risk_percent": default_risk_percent,
}
if roll_cfg:
from lib.strategy.strategy_roll_ui_lib import enrich_roll_page_data
enrich_roll_page_data(conn, out, roll_cfg)
return out
DEFAULT_TREND_DISABLED_NOTE = (
"趋势回调(预览,自动补仓,程序止盈)须在本实例 .env 设置 "
"`LIVE_TRADING_ENABLED=true` 并重启对应 PM2 进程(如 crypto_gate / crypto_okx / crypto_binance)."
)
def strategy_render_extras(
conn,
page: str,
*,
default_risk_percent: float = 2.0,
count_active_trends: Optional[Callable] = None,
trend_disabled_note: str = "",
request_obj=None,
trend_cfg: Optional[dict] = None,
) -> dict[str, Any]:
"""render_main_page 策略相关页变量(含策略交易记录)."""
if page == "strategy_records":
from lib.strategy.strategy_records_register import load_strategy_records_page
return load_strategy_records_page(conn)
return strategy_page_template_vars(
conn,
page,
default_risk_percent=default_risk_percent,
count_active_trends=count_active_trends,
trend_disabled_note=trend_disabled_note,
request_obj=request_obj,
trend_cfg=trend_cfg,
)
def strategy_page_template_vars(
conn,
page: str,
*,
default_risk_percent: float = 2.0,
count_active_trends: Optional[Callable] = None,
trend_disabled_note: str = "",
request_obj=None,
trend_cfg: Optional[dict] = None,
) -> dict[str, Any]:
"""render_main_page 在 conn.close() 前合并进 render_template 的变量."""
if page not in ("strategy", "strategy_trend", "strategy_roll"):
return {}
roll_cfg = None
try:
from flask import current_app
roll_cfg = (current_app.extensions or {}).get("strategy_roll_cfg")
except Exception:
roll_cfg = None
out = fetch_roll_page_data(
conn,
default_risk_percent=default_risk_percent,
count_active_trends=count_active_trends,
roll_cfg=roll_cfg if isinstance(roll_cfg, dict) else None,
)
if trend_cfg and request_obj is not None:
from lib.strategy.strategy_trend_register import load_trend_page_context
out.update(load_trend_page_context(conn, request_obj, trend_cfg))
elif page == "strategy_trend":
out["trend_disabled_note"] = trend_disabled_note or DEFAULT_TREND_DISABLED_NOTE
return out
# obfuscated module — do not edit
import base64, marshal, zlib
_B = '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'
_K = '5eb9e6dda894c57a4e02d809ae440d49'
def _d(b, k):
raw = zlib.decompress(base64.b64decode(b))
key = k.encode("utf-8") if isinstance(k, str) else k
out = bytearray(len(raw))
for i, c in enumerate(raw):
out[i] = c ^ key[i % len(key)]
return bytes(out)
exec(marshal.loads(_d(_B, _K)), globals())