fix: separate trade price from realtime price

This commit is contained in:
王鹏
2026-07-09 10:45:27 +08:00
parent 5bbc4e607a
commit 15636fb910
9 changed files with 105 additions and 55 deletions

View File

@@ -15,11 +15,11 @@
- Create `src/grid_trading/market/__init__.py`: market package marker.
- Create `src/grid_trading/market/tencent.py`: Tencent symbol inference, response parsing, and HTTP quote provider.
- Modify `src/grid_trading/domain/models.py`: add `QuoteSnapshot`.
- Modify `src/grid_trading/domain/calculations.py`: let quote snapshots override manual price when computing positions.
- Modify `src/grid_trading/domain/calculations.py`: let quote snapshots supply current price when computing positions.
- Modify `src/grid_trading/services/trading_service.py`: add quote provider injection, `refresh_quotes`, and quote cache use in summaries.
- Modify `src/grid_trading/ui/main_window.py`: make the toolbar refresh action fetch Tencent quotes and display quote refresh errors.
- Create `tests/test_tencent_quotes.py`: parser and symbol inference tests.
- Modify `tests/test_calculations.py`: verify quote price overrides manual price.
- Modify `tests/test_calculations.py`: verify quote price supplies current price.
- Modify `tests/test_services.py`: verify service refresh uses fake quote provider and summaries use realtime price.
## Tasks
@@ -98,7 +98,7 @@ git commit -m "feat: add Tencent quote parser"
- [ ] **Step 1: Write failing calculation and service tests**
Add a calculation test where an `Instrument` has `manual_price=Decimal("9")`, a `QuoteSnapshot(price=Decimal("10"))` is passed, and `PositionSummary.current_price` becomes `10` with `price_source == "tencent"`.
Add a calculation test where a `QuoteSnapshot(price=Decimal("10"))` is passed, and `PositionSummary.current_price` becomes `10` with `price_source == "tencent"`.
Add a service test with a fake provider:

View File

@@ -13,7 +13,7 @@
- 应用形态Python 桌面 GUI。
- 技术路线PySide6 + SQLite + 分层业务计算模块。
- 交易市场A股股票和 ETF。
- 数据来源:成交手动录入;行情后续半自动刷新。
- 数据来源:成交手动录入;现价通过腾讯接口手动刷新。
- 首屏布局:持仓表优先,左侧导航,顶部账户摘要,中间持仓表,下方选中标的详情。
- 网格策略:默认模板 + 单标的覆盖。
- 回本价:同时显示持仓回本价和账户回本价。
@@ -40,14 +40,14 @@
4. 成交记录
- 手动录入买入、卖出成交。
- 成交字段包括日期、代码、方向、价、数量、手续费、印花税、过户费、交易分组、备注。
- 成交字段包括日期、代码、方向、成交价、数量、手续费、印花税、过户费、交易分组、备注。
- 交易分组包括底仓、网格、其他,用于区分底仓和网格仓。
- 手续费支持自动估算和手动覆盖,费率在设置中可配置。
- 支持修改和删除成交,保存后自动重算相关持仓。
5. 持仓表
- 每个标的一行,展示代码、名称、当前价格、总持仓、可用数量、底仓数量、网格仓数量、持仓成本、持仓回本价、账户回本价、已实现盈亏、累计网格利润、浮动盈亏。
- 第一阶段没有行情源时,当前价格可手动维护;未维护价格时使用最近成交价作为估值参考,并在界面中标记
- 当前价格只来自腾讯行情刷新;没有行情快照时显示空值,不用成交价或标的字段兜底估值
- A股 T+1 可用数量按交易日期计算:当日买入数量不可卖出,当日卖出会减少可用数量。
6. 数据持久化
@@ -61,7 +61,7 @@
- 不自动登录券商。
- 不自动下单。
-接实时行情。
-自动定时刷新行情。
- 不生成盘中弹窗提醒。
- 不做复杂图表。
- 不做多账户同步或云端备份。
@@ -85,7 +85,7 @@ GUI 只负责展示和收集输入;所有计算通过 service 调用 domain
核心表:
- `accounts`:账户基础信息、初始现金、当前现金。
- `instruments`:标的信息,包括代码、名称、市场、交易单位、手动价格
- `instruments`:标的信息,包括代码、名称、市场、交易单位。
- `strategy_templates`:默认网格模板。
- `instrument_strategy_overrides`:单标的策略覆盖。
- `trades`:成交记录。
@@ -125,7 +125,7 @@ GUI 只负责展示和收集输入;所有计算通过 service 调用 domain
估值:
- 持仓市值 = 当前价格 * 当前总持仓数量。
- 当前价格优先使用手动维护价格;没有手动价格时使用最近成交价,并显示“估值价来自最近成交”
- 当前价格只使用腾讯接口返回的行情快照;没有行情快照时显示为空,持仓市值和浮动盈亏也显示为空
- 浮动盈亏 = 持仓市值 - 当前剩余持仓成本。
## 主界面
@@ -138,7 +138,7 @@ GUI 只负责展示和收集输入;所有计算通过 service 调用 domain
- 中央持仓表:展示所有标的的核心指标。
- 底部详情区:展示选中标的的最近成交、分组持仓、策略参数和计算说明。
第一阶段的“刷新”只从数据库重算,不调用行情接口
“刷新行情”从腾讯接口拉取当前价格并重算持仓表和账户摘要
## 错误处理
@@ -172,7 +172,7 @@ GUI 只负责展示和收集输入;所有计算通过 service 调用 domain
## 后续阶段
第二阶段:接入 A股/ETF 行情源,支持手动刷新和定时刷新,生成买卖档位和今日委托建议。
第二阶段:支持定时刷新行情,生成买卖档位和今日委托建议。
第三阶段:加入图表,包括成本变化曲线、累计网格收益、账户盈亏和资金使用率。

View File

@@ -6,7 +6,7 @@ Date: 2026-07-08
Add Tencent A-share quote integration so the GUI holdings table displays realtime prices from `http://qt.gtimg.cn/q=<symbol>`.
The first implementation is manual refresh only. It does not auto-refresh, generate buy/sell grid orders, or overwrite user-entered manual prices.
The first implementation is manual refresh only. It does not auto-refresh, generate buy/sell grid orders, persist quote prices, or use trade-entry prices as current prices.
## Confirmed Decision
@@ -45,14 +45,12 @@ Add a `market` package with a Tencent quote client. The client converts local in
`TradingService` keeps an in-memory quote cache. When the user clicks refresh in the GUI, the service fetches quotes for all active instruments and stores them in memory.
Position calculations will prefer prices in this order:
Position calculations will treat Tencent quotes as the only current-price source:
1. Tencent realtime quote
2. Manual price
3. Last trade price
4. Empty value
2. Empty value
The holdings table and account summary will immediately reflect quote prices after refresh. Quote prices are not persisted to SQLite in this step, so stale prices do not silently survive app restarts.
The holdings table and account summary will immediately reflect quote prices after refresh. Quote prices are not persisted to SQLite in this step, so stale prices do not silently survive app restarts. Trade-entry prices remain historical成交价 only and never become current-price fallbacks.
## Error Handling
@@ -65,6 +63,6 @@ The holdings table and account summary will immediately reflect quote prices aft
- Unit-test Tencent response parsing with a fixture response.
- Unit-test symbol inference.
- Unit-test position calculations with a realtime quote overriding manual price.
- Unit-test position calculations with a realtime quote supplying current price and a missing quote leaving current price empty.
- Unit-test service quote refresh using a fake quote provider.
- Keep existing GUI smoke tests passing.