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