docs: document Tencent quote refresh
This commit is contained in:
13
README.md
13
README.md
@@ -9,8 +9,21 @@
|
|||||||
- 配置默认网格策略模板。
|
- 配置默认网格策略模板。
|
||||||
- 手动录入、编辑、删除买入/卖出成交。
|
- 手动录入、编辑、删除买入/卖出成交。
|
||||||
- 自动计算持仓数量、T+1 可用数量、持仓成本、已实现盈亏、累计网格利润、持仓回本价、账户回本价。
|
- 自动计算持仓数量、T+1 可用数量、持仓成本、已实现盈亏、累计网格利润、持仓回本价、账户回本价。
|
||||||
|
- 点击“刷新行情”从腾讯接口获取实时价格,并用实时价更新持仓市值和账户摘要。
|
||||||
- 使用 SQLite 本地保存数据,默认路径为 `data/grid_trading.db`。
|
- 使用 SQLite 本地保存数据,默认路径为 `data/grid_trading.db`。
|
||||||
|
|
||||||
|
## 行情说明
|
||||||
|
|
||||||
|
行情刷新使用腾讯接口:
|
||||||
|
|
||||||
|
```text
|
||||||
|
http://qt.gtimg.cn/q=<symbol>
|
||||||
|
```
|
||||||
|
|
||||||
|
例如 `000001` 会自动转换为 `sz000001`,`600000` 会自动转换为 `sh600000`。
|
||||||
|
|
||||||
|
实时行情只保存在当前程序内存中,用于显示现价、持仓市值、浮动盈亏、总资产和资金使用率;不会覆盖标的里的手动价格,也不会写入 SQLite。关闭软件后再次打开,需要重新点击“刷新行情”。
|
||||||
|
|
||||||
## 开发环境
|
## 开发环境
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|||||||
import re
|
import re
|
||||||
from decimal import Decimal, InvalidOperation
|
from decimal import Decimal, InvalidOperation
|
||||||
from typing import Callable, Iterable
|
from typing import Callable, Iterable
|
||||||
|
from urllib.error import HTTPError, URLError
|
||||||
from urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
|
|
||||||
from grid_trading.domain.models import Instrument, QuoteSnapshot
|
from grid_trading.domain.models import Instrument, QuoteSnapshot
|
||||||
@@ -61,7 +62,10 @@ class TencentQuoteProvider:
|
|||||||
return {}
|
return {}
|
||||||
query = ",".join(symbols)
|
query = ",".join(symbols)
|
||||||
url = f"{self.endpoint}{query}"
|
url = f"{self.endpoint}{query}"
|
||||||
raw = self._fetcher(url, self.timeout)
|
try:
|
||||||
|
raw = self._fetcher(url, self.timeout)
|
||||||
|
except (OSError, HTTPError, URLError) as exc:
|
||||||
|
raise QuoteFetchError(f"Tencent quote request failed: {exc}") from exc
|
||||||
return {quote.code: quote for quote in parse_tencent_response(raw)}
|
return {quote.code: quote for quote in parse_tencent_response(raw)}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -64,3 +64,13 @@ def test_provider_builds_batch_query_and_maps_by_code():
|
|||||||
|
|
||||||
assert "q=sz000001" in calls[0]
|
assert "q=sz000001" in calls[0]
|
||||||
assert quotes["000001"].price == Decimal("10.60")
|
assert quotes["000001"].price == Decimal("10.60")
|
||||||
|
|
||||||
|
|
||||||
|
def test_provider_wraps_fetch_errors():
|
||||||
|
def failing_fetch(url: str, timeout: float) -> bytes:
|
||||||
|
raise OSError("bad gateway")
|
||||||
|
|
||||||
|
provider = TencentQuoteProvider(fetcher=failing_fetch)
|
||||||
|
|
||||||
|
with pytest.raises(QuoteFetchError, match="Tencent quote request failed"):
|
||||||
|
provider.fetch_quotes([Instrument(id=1, code="000001", name="平安银行")])
|
||||||
|
|||||||
Reference in New Issue
Block a user