feat: personal user edition v1.0.0-user on release branch
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,56 +1,57 @@
|
||||
# 国内期货 · 交易复盘系统
|
||||
# 国内期货 · 交易复盘系统 · 个人用户版
|
||||
|
||||
基于 Flask 的国内期货 **CTP 下单 + 监控 + 复盘 + 统计** Web 应用。模拟盘连接 SimNow,实盘连接期货公司 CTP;支持关键位/计划提醒、交易记录同步、资金曲线、可开仓品种(仓位纪律)与企业微信推送。
|
||||
> **发行标识**:`v1.0.0-user`(分支 `release/v1.0-user`)
|
||||
> 基于 Flask 的国内期货 **CTP 下单 + 监控 + 复盘 + 统计** Web 应用。模拟盘连接 SimNow,实盘连接期货公司 CTP。
|
||||
|
||||
本分支为 **个人用户版**,与完整版 `main` 功能范围不同,详见 [发行说明](docs/RELEASE-v1.0.0-user.md)。
|
||||
|
||||
## 用户版功能范围
|
||||
|
||||
| 包含 | 不含 |
|
||||
|------|------|
|
||||
| 下单监控(报单、持仓、CTP) | 行情 K 线页面 |
|
||||
| 关键位监控 | 可开仓品种筛选大表 |
|
||||
| 交易记录与复盘(**手动截图**) | 复盘自动生成 K 线图 |
|
||||
| 统计分析、系统设置、备份 | — |
|
||||
| **小账户四品种限制**(≤20 万或未连 CTP:玉米、豆粕、甲醇、螺纹钢) | — |
|
||||
|
||||
## 文档
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| **[功能说明](docs/FEATURES.md)** | 各模块功能、页面路径、数据库与后台任务 |
|
||||
| **[部署文档](docs/DEPLOY.md)** | 一键部署、更新、PM2、故障排查 |
|
||||
| **[备份与恢复](docs/BACKUP.md)** | 自动备份、下载、跨服务器恢复 |
|
||||
| **[发行说明 v1.0.0-user](docs/RELEASE-v1.0.0-user.md)** | 版本标识、与完整版差异、交付与升级 |
|
||||
| **[功能说明](docs/FEATURES.md)** | 各模块功能、页面路径 |
|
||||
| **[部署文档](docs/DEPLOY.md)** | 一键部署、PM2、故障排查 |
|
||||
| **[SimNow 接入](docs/SIMNOW.md)** | 仿真账号注册与 CTP 前置 |
|
||||
| **[期货公司实盘 CTP](docs/CTP_LIVE.md)** | 实盘接入、与 SimNow 开平仓对比 |
|
||||
| **[交易与策略](docs/TRADING.md)** | 下单、持仓、可开仓品种、策略 API |
|
||||
| **[手续费与导航](docs/FEES.md)** | CTP 费率同步、导航开关 |
|
||||
| **[软件购买与使用协议](docs/软件购买与使用协议.md)** | 个人版授权模板(含签署栏) |
|
||||
| **[交易与策略](docs/TRADING.md)** | 下单、小账户品种限制 |
|
||||
| **[软件购买与使用协议](docs/软件购买与使用协议.md)** | 个人版授权模板 |
|
||||
|
||||
## 功能一览
|
||||
|
||||
| 模块 | 路径 | 说明 |
|
||||
|------|------|------|
|
||||
| **下单监控**(默认首页) | `/positions` | CTP 连接、期货下单、当前持仓、可开仓品种 |
|
||||
| **策略交易** | `/strategy` | 趋势回调 / 顺势加仓(可导航开关) |
|
||||
| **开单计划** | `/plans` | 当日决策区间、触发推送(可开关) |
|
||||
| **关键位监控** | `/keys` | 箱体/阻力支撑突破提醒 |
|
||||
| **行情 K 线** | `/market` | 多周期 K 线(可开关) |
|
||||
| **交易记录与复盘** | `/records` | 资金曲线、CTP 成交同步、复盘上传 |
|
||||
| **统计分析** | `/stats` | 汇总指标 + 多维度分项统计 |
|
||||
| **手续费配置** | `/fees` | CTP / 本地费率(可开关) |
|
||||
| **系统设置** | `/settings` | 交易模式、CTP、计仓、微信、主题 |
|
||||
|
||||
登录后默认进入 **下单监控**;刷新当前页不会跳转,仅访问根路径 `/` 或新登录时进入默认页。
|
||||
| **下单监控**(默认首页) | `/positions` | CTP 连接、期货下单、当前持仓 |
|
||||
| 策略交易 | `/strategy` | 可导航开关 |
|
||||
| 开单计划 | `/plans` | 可导航开关 |
|
||||
| 关键位监控 | `/keys` | 箱体/阻力支撑突破提醒 |
|
||||
| 交易记录与复盘 | `/records` | 资金曲线、CTP 成交同步、手动复盘 |
|
||||
| 统计分析 | `/stats` | 汇总指标 + 分项统计 |
|
||||
| 手续费配置 | `/fees` | 可导航开关 |
|
||||
| 系统设置 | `/settings` | 交易模式、CTP、计仓、微信 |
|
||||
|
||||
## 快速开始
|
||||
|
||||
**服务器(Ubuntu)**
|
||||
|
||||
```bash
|
||||
cd /opt/qihuo && bash deploy.sh
|
||||
git clone https://gitee.com/dekun/qihuo.git /opt/qihuo
|
||||
cd /opt/qihuo
|
||||
git fetch --tags
|
||||
git checkout v1.0.0-user
|
||||
bash deploy.sh
|
||||
# 访问 http://<IP>:6600
|
||||
```
|
||||
|
||||
**更新**
|
||||
|
||||
```bash
|
||||
cd /opt/qihuo
|
||||
git fetch origin && git reset --hard origin/main
|
||||
source venv/bin/activate && pip install -r requirements.txt
|
||||
pm2 restart qihuo
|
||||
```
|
||||
|
||||
详见 [部署文档](docs/DEPLOY.md)。
|
||||
|
||||
**本地开发**
|
||||
|
||||
```bash
|
||||
@@ -61,27 +62,18 @@ cp .env.example .env
|
||||
python app.py
|
||||
```
|
||||
|
||||
## 品种与行情
|
||||
|
||||
- 合约代码:**同花顺格式**(`ag2606`、`SR609`、`IF2606`),中文联想匹配主力
|
||||
- 行情:默认 **新浪财经**;机构用户可配置同花顺 iFinD token
|
||||
|
||||
## 环境要求
|
||||
|
||||
- Python 3.10+(vnpy_ctp)
|
||||
- PM2(生产部署)
|
||||
- 网络:新浪行情、Git 仓库、SimNow/CTP 前置(见部署文档)
|
||||
|
||||
## 仓库
|
||||
|
||||
https://git.bz121.com/dekun/qihuo.git
|
||||
- 网络:新浪现价(内部逻辑)、SimNow/CTP 前置
|
||||
|
||||
## 版权与授权
|
||||
|
||||
- 著作权人:**马建军**
|
||||
- 许可说明:[LICENSE.zh-CN.txt](LICENSE.zh-CN.txt)
|
||||
- 个人购买协议模板:[docs/软件购买与使用协议.md](docs/软件购买与使用协议.md)
|
||||
- 个人购买协议:[docs/软件购买与使用协议.md](docs/软件购买与使用协议.md)
|
||||
|
||||
本软件为 **专有软件**,仅供经授权的个人自用部署。严禁用于带单、向他人推荐期货品种或买卖建议、融资配资、转售源码或搭建共享交易室等用途。本软件不构成投资建议,期货交易风险由使用者自行承担。
|
||||
本软件为 **专有软件**,仅供经授权的个人自用部署。
|
||||
|
||||
联系:手机 18364911125 · 微信 dekun03
|
||||
|
||||
@@ -44,7 +44,8 @@ from fee_specs import (
|
||||
count_fee_rates_by_source,
|
||||
purge_non_ctp_fee_rates,
|
||||
)
|
||||
from nav_settings import NAV_TOGGLES, get_nav_items, nav_enabled, save_nav_items
|
||||
from edition import EDITION_ID, EDITION_LABEL, USER_EDITION
|
||||
from nav_settings import NAV_TOGGLES, get_nav_items, nav_enabled, nav_toggles_for_settings, save_nav_items
|
||||
from stats_engine import (
|
||||
STATS_VIEWS,
|
||||
build_all_stats,
|
||||
@@ -266,7 +267,13 @@ def _ua_is_phone(ua: str) -> bool:
|
||||
|
||||
@app.context_processor
|
||||
def inject_globals():
|
||||
return {"nav_items": get_nav_items(get_setting), "asset_v": _static_asset_v()}
|
||||
return {
|
||||
"nav_items": get_nav_items(get_setting),
|
||||
"asset_v": _static_asset_v(),
|
||||
"user_edition": USER_EDITION,
|
||||
"edition_id": EDITION_ID,
|
||||
"edition_label": EDITION_LABEL,
|
||||
}
|
||||
|
||||
|
||||
def _trading_mode() -> str:
|
||||
@@ -765,16 +772,17 @@ def start_background_threads():
|
||||
from trading_context import get_trading_mode
|
||||
|
||||
threading.Thread(target=background_task, daemon=True).start()
|
||||
threading.Thread(
|
||||
target=lambda: kline_hub.worker_loop(
|
||||
DB_PATH,
|
||||
lambda sym, mc, sc: build_market_quote_payload(
|
||||
sym, mc, sc, prefer_sina=True,
|
||||
if not USER_EDITION:
|
||||
threading.Thread(
|
||||
target=lambda: kline_hub.worker_loop(
|
||||
DB_PATH,
|
||||
lambda sym, mc, sc: build_market_quote_payload(
|
||||
sym, mc, sc, prefer_sina=True,
|
||||
),
|
||||
get_mode_fn=lambda: get_trading_mode(get_setting),
|
||||
),
|
||||
get_mode_fn=lambda: get_trading_mode(get_setting),
|
||||
),
|
||||
daemon=True,
|
||||
).start()
|
||||
daemon=True,
|
||||
).start()
|
||||
threading.Thread(target=refresh_main_index, daemon=True).start()
|
||||
start_backup_worker(get_setting_fn=get_setting, set_setting_fn=set_setting)
|
||||
|
||||
@@ -867,7 +875,7 @@ def api_symbols_mains():
|
||||
@app.route("/api/symbols/recommended")
|
||||
@login_required
|
||||
def api_symbols_recommended():
|
||||
"""品种下拉:仅展示当前资金下可开仓品种(与下方可开仓品种表一致)。"""
|
||||
"""品种下拉:当前资金下可报单品种(小账户四品种限制;完整版与下方可开仓表一致)。"""
|
||||
from recommend_store import recommend_payload
|
||||
from trading_context import (
|
||||
get_fixed_lots,
|
||||
@@ -1506,7 +1514,7 @@ def add_review():
|
||||
)
|
||||
pnl_net = round((gross_pnl or 0) - fee, 2) if gross_pnl is not None else None
|
||||
|
||||
auto_kline = bool(d.get("auto_kline"))
|
||||
auto_kline = bool(d.get("auto_kline")) and not USER_EDITION
|
||||
if auto_kline and not screenshot:
|
||||
try:
|
||||
generated = generate_review_kline_chart(
|
||||
@@ -1732,6 +1740,9 @@ def api_dashboard_live():
|
||||
@login_required
|
||||
@require_nav("market")
|
||||
def market_page():
|
||||
if USER_EDITION:
|
||||
flash("个人用户版不含行情 K 线")
|
||||
return redirect(url_for("positions"))
|
||||
symbol = request.args.get("symbol", "").strip()
|
||||
period = request.args.get("period", "15m").strip()
|
||||
valid = {p["key"] for p in MARKET_PERIODS}
|
||||
@@ -1758,6 +1769,8 @@ def market_page():
|
||||
@app.route("/api/kline")
|
||||
@login_required
|
||||
def api_kline():
|
||||
if USER_EDITION:
|
||||
return jsonify({"error": "个人用户版不含行情 K 线"}), 403
|
||||
symbol = request.args.get("symbol", "").strip()
|
||||
period = request.args.get("period", "15m").strip()
|
||||
if not symbol:
|
||||
@@ -1781,6 +1794,8 @@ def api_kline():
|
||||
@app.route("/api/kline/stream")
|
||||
@login_required
|
||||
def api_kline_stream():
|
||||
if USER_EDITION:
|
||||
return jsonify({"error": "个人用户版不含行情 K 线"}), 403
|
||||
from queue import Empty
|
||||
|
||||
symbol = request.args.get("symbol", "").strip()
|
||||
@@ -2094,7 +2109,7 @@ def settings():
|
||||
flash_msg = f"CTP 配置已保存;{pwd_note or '请稍后在持仓监控页重连'}"
|
||||
flash(flash_msg)
|
||||
elif action == "nav":
|
||||
items = {k: request.form.get(f"nav_{k}") == "on" for k in NAV_TOGGLES}
|
||||
items = {k: request.form.get(f"nav_{k}") == "on" for k in nav_toggles_for_settings()}
|
||||
save_nav_items(set_setting, items)
|
||||
flash("导航显示已保存")
|
||||
elif action == "password":
|
||||
@@ -2143,7 +2158,7 @@ def settings():
|
||||
trailing_be_tick_buffer=get_setting("trailing_be_tick_buffer", "2"),
|
||||
pending_order_timeout_min=get_setting("pending_order_timeout_min", "5"),
|
||||
nav_items=get_nav_items(get_setting),
|
||||
nav_toggles=NAV_TOGGLES,
|
||||
nav_toggles=nav_toggles_for_settings(),
|
||||
backup_dir=str(backup_dir()),
|
||||
backup_last_at=get_backup_last_at(get_setting),
|
||||
backup_running=backup_in_progress(),
|
||||
|
||||
@@ -4,6 +4,22 @@
|
||||
|
||||
---
|
||||
|
||||
## 个人用户版 v1.0.0-user
|
||||
|
||||
客户交付请使用 **tag**,勿部署 `main`:
|
||||
|
||||
```bash
|
||||
git clone https://gitee.com/dekun/qihuo.git /opt/qihuo
|
||||
cd /opt/qihuo
|
||||
git fetch --tags
|
||||
git checkout v1.0.0-user
|
||||
bash deploy.sh
|
||||
```
|
||||
|
||||
功能范围见 [RELEASE-v1.0.0-user.md](./RELEASE-v1.0.0-user.md)。**你自己**的开发服务器继续用 `main` 即可。
|
||||
|
||||
---
|
||||
|
||||
## 部署概要
|
||||
|
||||
| 项目 | 默认值 |
|
||||
|
||||
+9
-24
@@ -1,9 +1,9 @@
|
||||
# 功能说明文档
|
||||
|
||||
国内期货 · 交易复盘系统(Flask + SQLite + vnpy_ctp + PM2)。
|
||||
国内期货 · 交易复盘系统 · **个人用户版 v1.0.0-user**(Flask + SQLite + vnpy_ctp + PM2)。
|
||||
|
||||
> **分板块详细说明(含下单逻辑、风控、微信模板)** → [INDEX.md](./INDEX.md)
|
||||
> 重点:[WECHAT.md](./WECHAT.md) · [AI.md](./AI.md) · [RISK.md](./RISK.md)
|
||||
> 完整版功能差异 → [RELEASE-v1.0.0-user.md](./RELEASE-v1.0.0-user.md)
|
||||
> 分板块详细说明 → [INDEX.md](./INDEX.md)
|
||||
|
||||
---
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
| 策略交易 | `/strategy` | 是 |
|
||||
| 开单计划 | `/plans` | 是 |
|
||||
| 关键位监控 | `/keys` | 否 |
|
||||
| 行情 K 线 | `/market` | 是 |
|
||||
| 交易记录与复盘 | `/records` | 否 |
|
||||
| 统计分析 | `/stats` | 否 |
|
||||
| AI 分析 | `/ai` | 是 |
|
||||
@@ -49,7 +48,7 @@
|
||||
|
||||
### 期货下单
|
||||
|
||||
- 品种联想(可开仓品种表与下拉一致;小账户或 CTP 未连接时仅四品种,见 [TRADING.md](./TRADING.md))
|
||||
- 品种联想(小账户或 CTP 未连接时仅四品种,见 [TRADING.md](./TRADING.md))
|
||||
- 方向、手数(固定手数 / 固定金额计仓)
|
||||
- 限价 / 市价(FAK)、止盈、止损
|
||||
- **移动保本**(默认关闭):开启后隐藏止盈与盈亏比,仅填止损;由移动止损监控平仓,不设固定止盈
|
||||
@@ -62,16 +61,12 @@
|
||||
- 持仓卡片:浮盈亏、保证金、止盈止损、平仓等
|
||||
- 数据经 SSE 推送,无需整页刷新
|
||||
|
||||
### 可开仓品种
|
||||
### 小账户品种限制
|
||||
|
||||
- 按当前权益与保证金上限筛选可开品种,养成开仓纪律、限制仓位
|
||||
- **权益 ≤20 万** 或 **CTP 未连接** 时,仅展示并可交易:玉米、豆粕、甲醇、螺纹钢(SimNow/实盘一致);未连接时最大手数按 **10 万权益** 估算
|
||||
- **夜盘时段** 仅显示有夜盘品种,并标注「夜盘」
|
||||
- **行业分类**、走势(多头/空头/震荡/转多/转空)、跳空、昨日成交量(手)、成交额
|
||||
- 支持行业筛选与多字段排序
|
||||
- 每日后台刷新缓存
|
||||
- **权益 ≤20 万** 或 **CTP 未连接** 时,品种下拉与开仓校验仅允许:玉米、豆粕、甲醇、螺纹钢
|
||||
- **夜盘时段** 品种下拉仅显示有夜盘品种
|
||||
|
||||
详见 [TRADING.md](./TRADING.md)。
|
||||
个人用户版 **不含**「可开仓品种」筛选大表(走势、成交量、行业排序等)。详见 [TRADING.md](./TRADING.md)。
|
||||
|
||||
---
|
||||
|
||||
@@ -106,16 +101,6 @@
|
||||
|
||||
---
|
||||
|
||||
## 行情 K 线
|
||||
|
||||
**路径**:`/market` · 详见 [MARKET.md](./MARKET.md)
|
||||
|
||||
- 多周期 K 线(TradingView Lightweight Charts)
|
||||
- 支持 CTP 连接后部分数据增强
|
||||
- 需在导航中开启
|
||||
|
||||
---
|
||||
|
||||
## 交易记录与复盘
|
||||
|
||||
**路径**:`/records`(`/trades` 重定向至此) · 详见 [RECORDS.md](./RECORDS.md)
|
||||
@@ -137,7 +122,7 @@
|
||||
|
||||
### 复盘上传 / 复盘历史
|
||||
|
||||
- 手动复盘表单、截图、自动 K 线图(matplotlib)
|
||||
- 手动复盘表单、**截图上传**(个人用户版不含自动 K 线图)
|
||||
- 按本日/本周/本月/自定义日期筛选历史
|
||||
|
||||
---
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@
|
||||
|-----|------|
|
||||
| `fees` | 手续费配置 |
|
||||
| `plans` | 开单计划 |
|
||||
| `market` | 行情 K 线 |
|
||||
| `market` | 行情 K 线(**用户版不含**) |
|
||||
| `strategy` | 策略交易 |
|
||||
|
||||
关闭后顶栏隐藏;直接访问 URL 会提示并跳转到 **下单监控**。
|
||||
|
||||
+5
-4
@@ -1,6 +1,8 @@
|
||||
# 文档索引
|
||||
# 文档索引 · 个人用户版 v1.0.0-user
|
||||
|
||||
国内期货 · 交易复盘系统各板块说明。每篇文档包含 **下单逻辑**、**风控规则**,并在需要时引用 [微信推送模板](./WECHAT.md)。
|
||||
国内期货 · 交易复盘系统各板块说明。
|
||||
|
||||
> **版本差异** → [RELEASE-v1.0.0-user.md](./RELEASE-v1.0.0-user.md)
|
||||
|
||||
---
|
||||
|
||||
@@ -26,7 +28,6 @@
|
||||
| 策略交易 | `/strategy` | [STRATEGY.md](./STRATEGY.md) |
|
||||
| 开单计划 | `/plans` | [PLANS.md](./PLANS.md) |
|
||||
| 关键位监控 | `/keys` | [KEY_MONITORS.md](./KEY_MONITORS.md) |
|
||||
| 行情 K 线 | `/market` | [MARKET.md](./MARKET.md) |
|
||||
| 交易记录与复盘 | `/records` | [RECORDS.md](./RECORDS.md) |
|
||||
| 统计分析 | `/stats` | [STATS.md](./STATS.md) |
|
||||
| 手续费配置 | `/fees` | [FEES.md](./FEES.md) |
|
||||
@@ -38,7 +39,7 @@
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [TRADING.md](./TRADING.md) | 可开仓品种、计仓、SimNow/实盘 |
|
||||
| [TRADING.md](./TRADING.md) | 小账户四品种、计仓、SimNow/实盘 |
|
||||
| [SIMNOW.md](./SIMNOW.md) | SimNow 仿真注册与接入 |
|
||||
| [CTP_LIVE.md](./CTP_LIVE.md) | **期货公司实盘 CTP** 与开平仓对比 |
|
||||
| [DEPLOY.md](./DEPLOY.md) | 部署说明 |
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# 行情 K 线
|
||||
|
||||
> **个人用户版 v1.0.0-user 不含本模块。** 本文档仅适用于完整版 `main`。用户版说明见 [RELEASE-v1.0.0-user.md](./RELEASE-v1.0.0-user.md)。
|
||||
|
||||
**页面路径**:`/market`
|
||||
|
||||
**相关文件**:`market.py`、`kline_chart.py`、`templates/market.html`
|
||||
|
||||
+8
-100
@@ -1,4 +1,4 @@
|
||||
# 下单监控
|
||||
# 下单监控 · 个人用户版
|
||||
|
||||
**页面路径**:`/positions`(默认首页)
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
| 顶栏 | 模拟/实盘、CTP 状态、风险状态、权益、连接按钮 |
|
||||
| 期货下单 | 手动开仓/平仓表单 |
|
||||
| 当前持仓 | pending 挂单 + active 持仓卡片 |
|
||||
| 可开仓品种 | 按权益与保证金筛选的推荐表 |
|
||||
|
||||
个人用户版 **不含**「可开仓品种」筛选大表。
|
||||
|
||||
---
|
||||
|
||||
@@ -38,114 +39,21 @@
|
||||
5. **成交后**:
|
||||
- 写入 `trade_order_monitors`(status=active 或 pending)
|
||||
- 注册本地 SL/TP 守护(`sl_tp_guard`)
|
||||
- 微信:结构化开仓推送(有止损)或简版
|
||||
- AI:后台开仓分析(有止损时)
|
||||
|
||||
### 挂单(限价未立即成交)
|
||||
### 小账户四品种
|
||||
|
||||
- status=`pending`,显示「挂单中」。
|
||||
- **超时撤单**:`pending_order_worker` 每 10 秒 reconcile(有 pending 时);默认超时见系统设置 `pending_order_timeout_sec`。
|
||||
- 微信:`委托已提交 · … 挂单中(N 分钟未成交自动撤单)`
|
||||
|
||||
### 手动平仓
|
||||
|
||||
- 市价平仓当前品种方向持仓。
|
||||
- 关闭对应 monitor,写入 `trade_logs`。
|
||||
- 若当日手动平仓次数超限 → 触发冷静期([RISK.md](./RISK.md))。
|
||||
- 微信:结构化平仓推送(成交同步后)。
|
||||
|
||||
### 止盈止损守护
|
||||
|
||||
后台 `sl_tp_guard` 线程 + tick 事件:
|
||||
|
||||
| 条件 | 动作 |
|
||||
|------|------|
|
||||
| 价格触及 **止盈价** | 市价平仓,结果=止盈 |
|
||||
| 价格触及 **止损价** | 市价平仓,结果=止损 |
|
||||
| 开启 **移动保本** | 见下节 |
|
||||
|
||||
触发时先推简版「平仓委托已提交」,成交写入 trade_logs 后推 **结构化平仓**。
|
||||
权益 ≤20 万或未连 CTP 时,非 `c` / `m` / `MA` / `rb` 品种开仓会被拒绝。品种下拉同样受限。
|
||||
|
||||
---
|
||||
|
||||
## 移动保本
|
||||
|
||||
**开启条件**:下单表单勾选「移动保本」,**必须填写止损**,不设固定止盈。
|
||||
|
||||
**逻辑**(`sl_tp_guard._update_trailing_stop_loss`):
|
||||
|
||||
| 浮盈 R 倍数 | 止损移动至 |
|
||||
|-------------|------------|
|
||||
| ≥ 1R | 开仓价 ± `trailing_be_tick_buffer` 跳(保本) |
|
||||
| ≥ 2R | 开仓价 ± 1R |
|
||||
| ≥ nR | 开仓价 ± (n−1)R |
|
||||
|
||||
**平仓结果标签**:
|
||||
|
||||
- 1R 锁定后止损出场 → **保本止盈**
|
||||
- 2R 及以上锁定后止损出场 → **移动止盈**
|
||||
|
||||
关键位自动单若开启移动保本且设目标盈亏比(默认 3R),达 TP 仍按 **止盈** 平仓;移动止损与显式 TP **可同时生效**。
|
||||
|
||||
---
|
||||
|
||||
## 风控规则
|
||||
|
||||
本板块执行 [RISK.md](./RISK.md) 全部规则,另加:
|
||||
|
||||
| 规则 | 说明 |
|
||||
|------|------|
|
||||
| 非交易时段 | 禁止开仓 |
|
||||
| 移动保本 | 必须填止损 |
|
||||
| 固定金额 | 必须填止损才能算手数 |
|
||||
| 保证金 | 新开仓前校验总占用 |
|
||||
| 单笔 50 手 | 超限拒绝 |
|
||||
|
||||
顶栏 **风险状态** 实时反映:正常 / 冷静期 / 日冻结 / 仓位上限。
|
||||
|
||||
---
|
||||
|
||||
## 可开仓品种表
|
||||
|
||||
- 按当前权益、`max_margin_pct`、合约保证金计算可开手数。
|
||||
- 权益 ≤20 万或 CTP 未连接:仅四品种;未连接按 10 万权益估算。
|
||||
- 夜盘时段过滤无夜盘品种。
|
||||
- 每日后台刷新 `product_recommend_cache`。
|
||||
|
||||
详见 [TRADING.md](./TRADING.md)。
|
||||
|
||||
---
|
||||
|
||||
## 微信推送
|
||||
|
||||
| 事件 | 模板 |
|
||||
|------|------|
|
||||
| 开仓成交(有止损) | [WECHAT §1](./WECHAT.md#1-手动开仓成功) |
|
||||
| 开仓成交(无止损) | [WECHAT §2](./WECHAT.md#2-简版开仓) |
|
||||
| 挂单提交 | [WECHAT §3](./WECHAT.md#3-挂单提交) |
|
||||
| 平仓完成 | [WECHAT §4](./WECHAT.md#4-平仓完成) |
|
||||
| SL/TP 触发 | [WECHAT §5](./WECHAT.md#5-本地止盈止损触发) |
|
||||
| AI 分析 | [AI.md](./AI.md)(仅页面,默认不推微信) |
|
||||
|
||||
---
|
||||
|
||||
## 数据流
|
||||
|
||||
```
|
||||
用户下单 → API /api/trade/order
|
||||
→ CTP 报单
|
||||
→ trade_order_monitors
|
||||
→ sl_tp_guard 监控
|
||||
→ 平仓 → trade_logs → 微信 + AI
|
||||
```
|
||||
|
||||
SSE:`/api/trading/stream` 推送持仓快照,无需整页刷新。
|
||||
见 [TRADING.md](./TRADING.md) 与完整版 ORDER_MONITOR 说明(逻辑相同)。
|
||||
|
||||
---
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [RISK.md](./RISK.md)
|
||||
- [WECHAT.md](./WECHAT.md)
|
||||
- [TRADING.md](./TRADING.md)
|
||||
- [SETTINGS.md](./SETTINGS.md)
|
||||
- [RISK.md](./RISK.md)
|
||||
- [RELEASE-v1.0.0-user.md](./RELEASE-v1.0.0-user.md)
|
||||
|
||||
+10
-21
@@ -1,4 +1,4 @@
|
||||
# 交易记录与复盘
|
||||
# 交易记录与复盘 · 个人用户版
|
||||
|
||||
**页面路径**:`/records`(`/trades` 重定向)
|
||||
|
||||
@@ -12,9 +12,11 @@
|
||||
|------|------|
|
||||
| 资金曲线 | Lightweight Charts,随主题变色 |
|
||||
| 交易记录 | `trade_logs` 主表 |
|
||||
| 复盘表单 | 手动复盘 + 截图 + 自动 K 线图 |
|
||||
| 复盘表单 | 手动复盘 + **截图上传** |
|
||||
| 复盘历史 | 按日/周/月/自定义筛选 |
|
||||
|
||||
个人用户版 **不含** 复盘「自动 K 线」选项(不调用新浪 K 线生成 matplotlib 截图)。
|
||||
|
||||
---
|
||||
|
||||
## 下单逻辑
|
||||
@@ -46,10 +48,6 @@
|
||||
- **日冻结** — 当日禁止新开仓([RISK.md](./RISK.md))
|
||||
- 手动平仓超限后的冷静期可因填写日记缩短为 **1 小时**
|
||||
|
||||
### 记录本身
|
||||
|
||||
交易记录页不改变持仓;删除/编辑仅影响本地数据库。
|
||||
|
||||
---
|
||||
|
||||
## 平仓后的联动
|
||||
@@ -61,25 +59,16 @@
|
||||
|
||||
---
|
||||
|
||||
## 主要字段
|
||||
## 复盘上传
|
||||
|
||||
品种、类型(monitor_type)、方向、开仓/平仓价、止损/止盈、手数、保证金、盈亏、手续费、净盈亏、最新资金、结果、持仓时长。
|
||||
|
||||
---
|
||||
|
||||
## 微信推送
|
||||
|
||||
| 事件 | 模板 |
|
||||
|------|------|
|
||||
| 程序/同步平仓 | [WECHAT §4](./WECHAT.md#4-平仓完成) |
|
||||
|
||||
开单计划结果见 [PLANS.md](./PLANS.md)(§10 简版模板)。
|
||||
- 填写开平仓时间、价格、止损止盈、行为标签等
|
||||
- **截图**:使用表单中的文件上传(`accept="image/*"`)
|
||||
- 个人用户版请自行截图保存 K 线或盘面,系统不会自动生成 K 线图
|
||||
|
||||
---
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [STATS.md](./STATS.md) — 统计来源 trade_logs
|
||||
- [RISK.md](./RISK.md) — 复盘触发冻结
|
||||
- [FEATURES.md](./FEATURES.md)
|
||||
- [RELEASE-v1.0.0-user.md](./RELEASE-v1.0.0-user.md)
|
||||
- [WECHAT.md](./WECHAT.md)
|
||||
- [AI.md](./AI.md)
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
# v1.0.0-user 个人用户版 · 发行说明
|
||||
|
||||
**Tag**:`v1.0.0-user`
|
||||
**分支**:`release/v1.0-user`
|
||||
**完整版开发线**:`main`(功能更多,勿与客户环境混用)
|
||||
|
||||
---
|
||||
|
||||
## 版本定位
|
||||
|
||||
面向 **个人购买者** 的首次交付版本:聚焦 **CTP 下单纪律、关键位、记录复盘与统计**,去掉易引发误解或依赖新浪 K 线展示的功能模块。
|
||||
|
||||
本软件为 **交易纪律与记录辅助工具**,不构成投资建议。
|
||||
|
||||
---
|
||||
|
||||
## 包含功能
|
||||
|
||||
| 模块 | 路径 |
|
||||
|------|------|
|
||||
| 下单监控 | `/positions` |
|
||||
| 关键位监控 | `/keys` |
|
||||
| 交易记录与复盘 | `/records` |
|
||||
| 统计分析 | `/stats` |
|
||||
| 系统设置 / 备份 | `/settings` |
|
||||
| 策略交易、开单计划、AI、手续费等 | 可在导航中开关(默认以交付时配置为准) |
|
||||
|
||||
### 小账户品种限制(保留)
|
||||
|
||||
- 权益 **≤20 万元** 或 **CTP 未连接** 时,仅可浏览、搜索、报单:**玉米、豆粕、甲醇、螺纹钢**
|
||||
- 品种下拉与开仓 API 校验一致
|
||||
- **不含**「可开仓品种」筛选大表(走势、成交量、行业排序等)
|
||||
|
||||
---
|
||||
|
||||
## 不含功能
|
||||
|
||||
| 功能 | 说明 |
|
||||
|------|------|
|
||||
| 行情 K 线 | 无 `/market` 页面;无 K 线 SSE |
|
||||
| 可开仓品种表 | 无下单页下方大表;无 recommend SSE |
|
||||
| 复盘自动 K 线 | 复盘请 **手动上传截图** |
|
||||
|
||||
---
|
||||
|
||||
## 部署(SSH 代部署)
|
||||
|
||||
```bash
|
||||
git clone https://gitee.com/dekun/qihuo.git /opt/qihuo
|
||||
cd /opt/qihuo
|
||||
git fetch --tags
|
||||
git checkout v1.0.0-user
|
||||
bash deploy.sh
|
||||
nano /opt/qihuo/.env # ADMIN_*、SIMNOW_* 等
|
||||
pm2 restart qihuo
|
||||
```
|
||||
|
||||
验收:
|
||||
|
||||
- 顶栏无「行情 K 线」
|
||||
- `/positions` 无「可开仓品种」大表
|
||||
- `/records` 无「自动 K 线」选项
|
||||
- 小账户四品种限制生效
|
||||
|
||||
详见 [DEPLOY.md](./DEPLOY.md)。
|
||||
|
||||
---
|
||||
|
||||
## 与完整版(main)的关系
|
||||
|
||||
| | 个人用户版 | 完整版 main |
|
||||
|--|-----------|-------------|
|
||||
| 代码线 | `release/v1.0-user` | `main` |
|
||||
| 行情 K 线 | 无 | 有 |
|
||||
| 可开仓品种表 | 无 | 有 |
|
||||
| 复盘自动 K 线 | 无 | 有 |
|
||||
| 小账户四品种 | 有 | 有 |
|
||||
|
||||
- 用户版 bug 修复:在 `release/v1.0-user` 发 `v1.0.1-user` 等 patch tag
|
||||
- 完整版新功能:**不会**自动进入用户版;客户升级需另议
|
||||
|
||||
---
|
||||
|
||||
## 协议与交付
|
||||
|
||||
- 协议附件填写:**版本 tag `v1.0.0-user`**
|
||||
- 交付:SSH 部署 + 管理员账号 + 本文档与 [FEATURES.md](./FEATURES.md)
|
||||
- 不提供 `main` 分支写权限
|
||||
|
||||
---
|
||||
|
||||
## 技术说明
|
||||
|
||||
- 发行标识:`edition.py` 中 `USER_EDITION = True`
|
||||
- 现价报价(新浪 `hq.sinajs.cn`)仍用于计划、关键位等内部逻辑;**不对用户提供 K 线浏览服务**
|
||||
- 关键位监控后台可能使用 K 线数据计算箱体(用户不可见)
|
||||
|
||||
---
|
||||
|
||||
## 联系
|
||||
|
||||
著作权人:马建军 · 手机 18364911125 · 微信 dekun03
|
||||
+7
-7
@@ -58,13 +58,13 @@
|
||||
|
||||
`nav_settings.py` 中 `NAV_TOGGLES` 控制菜单可见性;`@require_nav` 保护路由。
|
||||
|
||||
| 键 | 菜单 |
|
||||
|----|------|
|
||||
| strategy | 策略交易 |
|
||||
| plans | 开单计划 |
|
||||
| market | 行情 K 线 |
|
||||
| fees | 手续费配置 |
|
||||
| ai | AI 分析 |
|
||||
| 键 | 菜单 | 用户版 |
|
||||
|----|------|--------|
|
||||
| strategy | 策略交易 | 可开关 |
|
||||
| plans | 开单计划 | 可开关 |
|
||||
| market | 行情 K 线 | **不含**(设置中不显示) |
|
||||
| fees | 手续费配置 | 可开关 |
|
||||
| ai | AI 分析 | 可开关 |
|
||||
|
||||
下单监控、关键位、记录、统计、设置 **不可关闭**。
|
||||
|
||||
|
||||
+20
-60
@@ -1,4 +1,4 @@
|
||||
# 下单监控与策略交易
|
||||
# 下单监控与策略交易 · 个人用户版
|
||||
|
||||
## 默认首页
|
||||
|
||||
@@ -9,9 +9,8 @@
|
||||
| 顶栏 | 交易模式、CTP 状态、权益/可用、连接 CTP |
|
||||
| 期货下单 | 限价/市价报单、止盈/止损、移动保本、以损定仓/固定手数 |
|
||||
| 当前持仓 | CTP 持仓卡片、挂单中、撤单、平仓 |
|
||||
| 可开仓品种 | 按权益与保证金上限筛选、行业分类、走势/跳空/成交量排序 |
|
||||
|
||||
`/trade`、`/recommend` 均重定向到 `/positions`(可开仓品种锚点 `#recommend`)。
|
||||
个人用户版 **不含** 下单页下方的「可开仓品种」筛选大表。`/trade`、`/recommend` 重定向至 `/positions`。
|
||||
|
||||
## 两种交易通道
|
||||
|
||||
@@ -21,7 +20,7 @@
|
||||
| **实盘** | 期货公司 CTP(`.env` 中 `CTP_LIVE_*`) | 柜台权益 |
|
||||
|
||||
模拟盘与实盘均走 **vnpy_ctp**,无本地假撮合。
|
||||
**实盘接入与开平仓对比** → [CTP_LIVE.md](./CTP_LIVE.md) · SimNow → [SIMNOW.md](./SIMNOW.md)
|
||||
**实盘接入** → [CTP_LIVE.md](./CTP_LIVE.md) · SimNow → [SIMNOW.md](./SIMNOW.md)
|
||||
|
||||
## 下单与持仓
|
||||
|
||||
@@ -30,18 +29,7 @@
|
||||
- **平仓**:程序平仓写入 `trade_logs`(来源「本地」)
|
||||
- **持仓数据**:SSE `/api/trading/stream` 推送,约 1 秒刷新
|
||||
|
||||
## 可开仓品种
|
||||
|
||||
- 用于开仓纪律与仓位限制:按保证金上限计算最大手数,仅展示当前权益下可开的品种
|
||||
- 每日后台刷新列表(`/api/recommend/stream`)
|
||||
- 最大手数 = floor(权益 × 保证金上限 ÷ 1 手保证金)
|
||||
- **1 手保证金**:**CTP 已连接** 时优先读取柜台合约的 `long_margin_ratio` / `short_margin_ratio` 与乘数计算(表格标注「柜台」);未连接或合约信息暂不可用时,才用本地参考保证金率估算
|
||||
- 开仓前校验、固定金额计仓、保证金占用比例检查均与上述规则一致,避免交易所上调保证金后仍按旧比例显示可开手数
|
||||
- 展示近一周日线走势、跳空、昨日成交量(手)、成交额
|
||||
- 可按 **行业** 筛选,支持多字段排序
|
||||
- **夜盘时段**:品种下拉与可开仓表仅显示有夜盘交易的品种,并带「夜盘」标记
|
||||
|
||||
### 小账户品种范围(≤20 万)
|
||||
## 小账户品种范围(≤20 万)
|
||||
|
||||
权益 **不超过 20 万元** 时,系统限制可浏览、可搜索、可报单的品种为以下 **4 个**:
|
||||
|
||||
@@ -54,13 +42,14 @@
|
||||
|
||||
适用范围:
|
||||
|
||||
- 可开仓品种表
|
||||
- 期货下单品种联想 / 下拉
|
||||
- 开仓报单校验(含趋势策略首仓)
|
||||
|
||||
**SimNow 与实盘规则一致**:**CTP 未连接** 时,可开仓表 **当前权益固定按 10 万** 估算最大手数,并 **仅展示四品种**(玉米、豆粕、甲醇、螺纹钢);与系统设置中的参考资金无关。连接 CTP 后改用柜台权益;若柜台权益 ≤20 万,同样仅上述四品种。
|
||||
**SimNow 与实盘规则一致**:**CTP 未连接** 时,品种下拉 **仅展示四品种**(玉米、豆粕、甲醇、螺纹钢);与系统设置中的参考资金无关。连接 CTP 后改用柜台权益;若柜台权益 ≤20 万,同样仅上述四品种。
|
||||
|
||||
页面会提示:「未连接 CTP,按 10 万权益估算最大手数,仅显示并可交易 …」。
|
||||
页面会提示小账户范围说明(在下单区底部)。
|
||||
|
||||
> 完整版另有「可开仓品种」大表(按保证金筛选、走势/成交量排序);**个人用户版不含该表**。
|
||||
|
||||
## 期货下单 · 止盈止损与移动保本
|
||||
|
||||
@@ -78,51 +67,22 @@
|
||||
|
||||
| 表单项 | 行为 |
|
||||
|--------|------|
|
||||
| 止盈 | **隐藏**,不提交止盈价 |
|
||||
| 盈亏比 / 止盈金额 | **不显示** |
|
||||
| 止损 | **必填**,仅保留止损输入 |
|
||||
| 止盈 | 隐藏 |
|
||||
| 止损 | 必填 |
|
||||
| 盈亏比提示 | 隐藏 |
|
||||
| 平仓逻辑 | 达 1R 后止损移至开仓价 ± 缓冲跳;2R 移 1R,依次类推 |
|
||||
|
||||
平仓逻辑:
|
||||
|
||||
- **不再** 按固定止盈价监控
|
||||
- 程序按 **移动止损** 管理出场:浮盈达 **1R** 后止损移至开仓价 ± N 跳(保本);达 **2R** 移至 1R,依次类推(N 见系统设置「移动保本缓冲」)
|
||||
- 开启移动保本 **必须填写止损价**,否则无法开仓
|
||||
|
||||
持仓卡片在开启移动保本时同样 **不展示盈亏比、盈利金额、止盈状态**,仅保留止损与移动保本进度(如已锁 N R)。
|
||||
详见 [ORDER_MONITOR.md](./ORDER_MONITOR.md#移动保本)。
|
||||
|
||||
## 策略交易
|
||||
|
||||
| 页面 | 路径 |
|
||||
|------|------|
|
||||
| 策略交易 | `/strategy` |
|
||||
| 策略记录 | `/strategy/records` |
|
||||
**路径**:`/strategy` · 详见 [STRATEGY.md](./STRATEGY.md)
|
||||
|
||||
趋势回调、顺势加仓等策略需先在下单监控完成开仓,再在策略页配置。
|
||||
- 趋势回调、顺势加仓等(需 CTP 已连接)
|
||||
- 策略记录单独归档
|
||||
|
||||
## 参考资金
|
||||
## 相关文档
|
||||
|
||||
系统设置中的「参考资金」在 **CTP 未连接** 时用于以损定仓估算;连接后自动改用柜台权益。
|
||||
|
||||
可开仓品种与品种白名单:**未连接 CTP 时** 可开仓表按 **10 万权益** 估算最大手数,且仅四品种;连接后若柜台权益 ≤20 万,同样仅上述四品种。
|
||||
|
||||
## 首次使用 SimNow
|
||||
|
||||
完整步骤见 **[SimNow 注册与接入说明](./SIMNOW.md)**。
|
||||
|
||||
简要:注册 SimNow → 填写 `.env` → 安装 vnpy_ctp → 登录系统 → **下单监控** → **连接 CTP**。
|
||||
|
||||
## 主要 API
|
||||
|
||||
| 接口 | 说明 |
|
||||
|------|------|
|
||||
| `POST /api/ctp/connect` | 连接 SimNow 或实盘 CTP |
|
||||
| `GET /api/ctp/status` | 连接状态 |
|
||||
| `POST /api/trade/order` | 报单(需已连接 CTP) |
|
||||
| `POST /api/trading/order/cancel` | 撤单(交易时段) |
|
||||
| `POST /api/trading/close` | 平仓 |
|
||||
| `GET /api/trading/stream` | 持仓 SSE |
|
||||
| `GET /api/recommend/list` | 可开仓品种 JSON |
|
||||
| `GET /api/recommend/stream` | 可开仓品种 SSE |
|
||||
| `POST /api/strategy/trend/execute` | 执行趋势策略 |
|
||||
|
||||
详见 [DEPLOY.md](./DEPLOY.md) 中 CTP 故障排查。
|
||||
- [ORDER_MONITOR.md](./ORDER_MONITOR.md)
|
||||
- [RISK.md](./RISK.md)
|
||||
- [RELEASE-v1.0.0-user.md](./RELEASE-v1.0.0-user.md)
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2025-2026 马建军. All rights reserved.
|
||||
# 专有软件 — 未经授权禁止复制、传播、转售。
|
||||
# 详见 LICENSE.zh-CN.txt 与 docs/软件购买与使用协议.md
|
||||
|
||||
"""发行版标识:release/v1.0-user 分支为个人用户版(v1.0.0-user)。"""
|
||||
|
||||
USER_EDITION = True
|
||||
EDITION_ID = "v1.0.0-user"
|
||||
EDITION_LABEL = "个人用户版"
|
||||
+17
-8
@@ -15,6 +15,8 @@ from typing import Any, Callable, Optional
|
||||
|
||||
from flask import flash, jsonify, redirect, render_template, request, url_for, Response, stream_with_context
|
||||
|
||||
from edition import USER_EDITION
|
||||
|
||||
from contract_specs import calc_position_metrics, get_contract_spec
|
||||
from fee_specs import calc_fee_breakdown
|
||||
from kline_stream import sse_format
|
||||
@@ -1858,12 +1860,13 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
|
||||
try:
|
||||
payload = _refresh_trading_live_snapshot(fast=fast)
|
||||
position_hub.broadcast("positions", payload)
|
||||
conn = get_db()
|
||||
try:
|
||||
rec = _recommend_payload(conn)
|
||||
recommend_hub.broadcast("recommend", {"ok": True, **rec})
|
||||
finally:
|
||||
conn.close()
|
||||
if not USER_EDITION:
|
||||
conn = get_db()
|
||||
try:
|
||||
rec = _recommend_payload(conn)
|
||||
recommend_hub.broadcast("recommend", {"ok": True, **rec})
|
||||
finally:
|
||||
conn.close()
|
||||
except Exception as exc:
|
||||
logger.debug("push position snapshot: %s", exc)
|
||||
|
||||
@@ -2070,8 +2073,8 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
|
||||
max_margin_pct=get_max_margin_pct(get_setting),
|
||||
pending_order_timeout_min=get_pending_order_timeout_min(get_setting),
|
||||
ctp_auto_connect=is_ctp_auto_connect_enabled(get_setting),
|
||||
recommend_rows=rec_cache.get("rows") or [],
|
||||
recommend_updated_at=rec_cache.get("updated_at"),
|
||||
recommend_rows=[] if USER_EDITION else (rec_cache.get("rows") or []),
|
||||
recommend_updated_at=None if USER_EDITION else rec_cache.get("updated_at"),
|
||||
night_session=is_night_trading_session(),
|
||||
small_account_scope=should_apply_small_account_scope(
|
||||
capital, ctp_connected=ctp_connected,
|
||||
@@ -2090,6 +2093,8 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
|
||||
@app.route("/recommend")
|
||||
@login_required
|
||||
def recommend_page():
|
||||
if USER_EDITION:
|
||||
return redirect(url_for("positions"))
|
||||
return redirect(url_for("positions") + "#recommend")
|
||||
|
||||
@app.route("/api/trading/live")
|
||||
@@ -2992,6 +2997,8 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
|
||||
@app.route("/api/recommend/stream")
|
||||
@login_required
|
||||
def api_recommend_stream():
|
||||
if USER_EDITION:
|
||||
return jsonify({"ok": False, "error": "个人用户版不含可开仓品种表"}), 403
|
||||
from queue import Empty
|
||||
|
||||
def generate():
|
||||
@@ -3026,6 +3033,8 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
|
||||
@login_required
|
||||
def api_recommend_refresh():
|
||||
"""手动触发一次后台刷新(仍写入数据库)。"""
|
||||
if USER_EDITION:
|
||||
return jsonify({"ok": False, "error": "个人用户版不含可开仓品种表"}), 403
|
||||
conn = get_db()
|
||||
try:
|
||||
init_strategy_tables(conn)
|
||||
|
||||
+20
-1
@@ -9,6 +9,8 @@ from __future__ import annotations
|
||||
import json
|
||||
from typing import Callable
|
||||
|
||||
from edition import USER_EDITION
|
||||
|
||||
# 可在系统设置中开关的导航项
|
||||
NAV_TOGGLES: dict[str, str] = {
|
||||
"dashboard": "数据看板",
|
||||
@@ -20,7 +22,18 @@ NAV_TOGGLES: dict[str, str] = {
|
||||
"ai": "AI 分析",
|
||||
}
|
||||
|
||||
_USER_EDITION_NAV_HIDDEN = frozenset({"market"})
|
||||
|
||||
DEFAULT_NAV: dict[str, bool] = {k: True for k in NAV_TOGGLES}
|
||||
if USER_EDITION:
|
||||
DEFAULT_NAV["market"] = False
|
||||
|
||||
|
||||
def nav_toggles_for_settings() -> dict[str, str]:
|
||||
"""系统设置页展示的导航开关(用户版隐藏行情 K 线)。"""
|
||||
if not USER_EDITION:
|
||||
return dict(NAV_TOGGLES)
|
||||
return {k: v for k, v in NAV_TOGGLES.items() if k not in _USER_EDITION_NAV_HIDDEN}
|
||||
|
||||
|
||||
def get_nav_items(get_setting: Callable[[str, str], str]) -> dict[str, bool]:
|
||||
@@ -36,18 +49,24 @@ def get_nav_items(get_setting: Callable[[str, str], str]) -> dict[str, bool]:
|
||||
out[k] = bool(data[k])
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
if USER_EDITION:
|
||||
out["market"] = False
|
||||
return out
|
||||
|
||||
|
||||
def save_nav_items(set_setting: Callable[[str, str], None], items: dict[str, bool]) -> None:
|
||||
merged = dict(DEFAULT_NAV)
|
||||
for k in NAV_TOGGLES:
|
||||
for k in nav_toggles_for_settings():
|
||||
if k in items:
|
||||
merged[k] = bool(items[k])
|
||||
if USER_EDITION:
|
||||
merged["market"] = False
|
||||
set_setting("nav_items", json.dumps(merged, ensure_ascii=False))
|
||||
|
||||
|
||||
def nav_enabled(get_setting: Callable[[str, str], str], key: str) -> bool:
|
||||
if USER_EDITION and key == "market":
|
||||
return False
|
||||
if key not in NAV_TOGGLES:
|
||||
return True
|
||||
return get_nav_items(get_setting).get(key, True)
|
||||
|
||||
@@ -121,6 +121,7 @@ min-height:100vh;
|
||||
.page-wrap{max-width:1800px;margin:0 auto;min-height:100vh}
|
||||
.site-header{text-align:center;padding:1.5rem 1rem 1.25rem;border-bottom:1px solid var(--border-header);position:relative}
|
||||
.site-title{font-size:1.75rem;font-weight:700;color:var(--text-title);margin-bottom:1.65rem;line-height:1.3}
|
||||
.site-edition-tag{display:inline-block;margin-left:.45rem;padding:.12rem .45rem;font-size:.62rem;font-weight:600;vertical-align:middle;border-radius:4px;background:var(--accent-dim, rgba(56,189,248,.15));color:var(--accent,#38bdf8);letter-spacing:.02em}
|
||||
.header-tools{position:absolute;top:1rem;left:1.5rem;display:flex;gap:.5rem;align-items:center;z-index:20}
|
||||
.theme-switch{
|
||||
display:inline-flex;align-items:center;
|
||||
|
||||
+17
-6
@@ -46,6 +46,7 @@
|
||||
var REC_INDUSTRY_CACHE = 'qihuo_rec_industry_v1';
|
||||
var REC_COLSPAN = 18;
|
||||
var marketNavEnabled = false;
|
||||
var userEdition = false;
|
||||
var productCategories = [];
|
||||
var POS_CACHE_KEY = 'qihuo_trading_live_v5';
|
||||
|
||||
@@ -58,6 +59,7 @@
|
||||
if (sizingMode === 'risk') sizingMode = 'amount';
|
||||
ctpAutoConnectEnabled = cfg.ctp_auto_connect !== false;
|
||||
marketNavEnabled = !!cfg.market_nav_enabled;
|
||||
userEdition = !!cfg.user_edition;
|
||||
productCategories = cfg.product_categories || [];
|
||||
window.TRADE_FIXED_LOTS = cfg.fixed_lots;
|
||||
window.TRADE_FIXED_AMOUNT = cfg.fixed_amount;
|
||||
@@ -1939,15 +1941,24 @@
|
||||
connectPositionStream();
|
||||
bindSlTpModal();
|
||||
initCtpOnLoad();
|
||||
connectRecommendStream();
|
||||
initRecommendSortControls();
|
||||
if (window.__RECOMMEND_ROWS__ && window.__RECOMMEND_ROWS__.length) {
|
||||
recRowsRaw = window.__RECOMMEND_ROWS__.slice();
|
||||
renderRecommendTable();
|
||||
if (!userEdition) {
|
||||
connectRecommendStream();
|
||||
initRecommendSortControls();
|
||||
if (window.__RECOMMEND_ROWS__ && window.__RECOMMEND_ROWS__.length) {
|
||||
recRowsRaw = window.__RECOMMEND_ROWS__.slice();
|
||||
renderRecommendTable();
|
||||
}
|
||||
}
|
||||
fetch('/api/recommend/list')
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (data) { if (data.ok) renderRecommendations(data); })
|
||||
.then(function (data) {
|
||||
if (!data.ok) return;
|
||||
if (userEdition) {
|
||||
updateRecommendMaxMaps(data);
|
||||
return;
|
||||
}
|
||||
renderRecommendations(data);
|
||||
})
|
||||
.catch(function () {});
|
||||
updateSessionUi();
|
||||
updateRRDisplay();
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@
|
||||
</button>
|
||||
<h1 class="site-title">
|
||||
<span class="site-title-mobile">期货监控</span>
|
||||
<span class="site-title-desktop">国内期货 · 交易复盘系统<span class="site-title-sub">Position Management · Disciplined Execution</span></span>
|
||||
<span class="site-title-desktop">国内期货 · 交易复盘系统{% if user_edition %}<span class="site-edition-tag">{{ edition_id }}</span>{% endif %}<span class="site-title-sub">Position Management · Disciplined Execution</span></span>
|
||||
</h1>
|
||||
<div class="header-tools">
|
||||
<div class="theme-switch" role="group" aria-label="主题模式">
|
||||
|
||||
@@ -350,6 +350,7 @@
|
||||
<textarea name="notes" placeholder="备注" rows="1"></textarea>
|
||||
<button type="submit" class="btn-primary">保存</button>
|
||||
</div>
|
||||
{% if not user_edition %}
|
||||
<div class="kline-row">
|
||||
<label><input type="checkbox" name="auto_kline" value="1" checked> 自动K线</label>
|
||||
<select name="kline_period1" title="周期1">{% for p in kline_periods %}<option value="{{ p }}" {% if p=='15m' %}selected{% endif %}>{{ p }}</option>{% endfor %}</select>
|
||||
@@ -357,6 +358,9 @@
|
||||
<input name="kline_count" type="number" value="300" placeholder="K线数" title="K线数">
|
||||
<select name="kline_cutoff" title="K线截止">{% for c in kline_cutoffs %}<option value="{{ c }}">{{ c }}</option>{% endfor %}</select>
|
||||
</div>
|
||||
{% else %}
|
||||
<p class="section-hint">个人用户版请使用截图上传复盘;不含自动 K 线图。</p>
|
||||
{% endif %}
|
||||
<p class="section-hint">勾选行为标签即为情绪单</p>
|
||||
<div class="tag-grid">
|
||||
{% for tag in behavior_tags %}
|
||||
|
||||
@@ -76,9 +76,10 @@
|
||||
<li><strong>移动保本</strong>:须填止损、不设固定止盈;达 1R 止损移至开仓±缓冲跳,2R 移 1R,依次类推</li>
|
||||
<li>手动平仓写入交易记录;当日手动平仓次数超限 → 进入冷静期</li>
|
||||
</ul>
|
||||
<p><strong>可开仓品种表</strong></p>
|
||||
<p><strong>小账户品种限制</strong></p>
|
||||
<ul>
|
||||
<li>按权益与保证金上限筛选;权益 ≤20 万或 CTP 未连接时仅四品种(玉米、豆粕、甲醇、螺纹钢)</li>
|
||||
<li>权益 ≤20 万或 CTP 未连接时,仅可交易玉米、豆粕、甲醇、螺纹钢</li>
|
||||
<li>品种下拉与开仓校验与上述规则一致;保证金占用不超过系统设置上限</li>
|
||||
</ul>
|
||||
</div>
|
||||
</details>
|
||||
@@ -142,6 +143,9 @@
|
||||
|
||||
<div class="trade-footer" id="trade-footer">
|
||||
<p class="hint" id="trade-metrics-hint">填写品种后显示精度与每跳价值;策略自动化请用 <a href="{{ url_for('strategy_page') }}">策略交易</a>。</p>
|
||||
{% if user_edition and small_account_scope %}
|
||||
<p class="hint text-muted">{{ small_account_scope_hint }}{% if small_account_margin_rec %} · {{ small_account_margin_rec.label }}{% endif %}</p>
|
||||
{% endif %}
|
||||
{% if ctp_status.last_error %}
|
||||
<p class="text-loss ctp-install-hint" style="font-size:.78rem;margin-top:.35rem">{{ ctp_status.last_error }}</p>
|
||||
{% endif %}
|
||||
@@ -169,6 +173,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if not user_edition %}
|
||||
<div class="card trade-card trade-card-full" id="recommend">
|
||||
<h2>可开仓品种</h2>
|
||||
<div class="card-body">
|
||||
@@ -268,6 +273,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div id="sl-tp-modal" class="modal-mask" role="dialog" aria-labelledby="sl-tp-modal-title">
|
||||
@@ -299,6 +305,7 @@
|
||||
<script type="application/json" id="trade-page-data">{{ {
|
||||
'sizing_mode': sizing_mode,
|
||||
'market_nav_enabled': nav_items.market,
|
||||
'user_edition': user_edition,
|
||||
'fixed_lots': fixed_lots,
|
||||
'fixed_amount': fixed_amount,
|
||||
'product_categories': product_categories | default([]),
|
||||
|
||||
Reference in New Issue
Block a user