docs(readme): write the fallback chains in the order the loader walks

Crypto read okx · ccxt · binance and forex mt5 · yfinance · akshare in
all seven READMEs, while FALLBACK_CHAINS walks binance before ccxt and
akshare before yfinance. The note "futures / fund / macro → tushare /
akshare" was stale too: futures is akshare → local (#1395), funds
tushare → akshare, macro akshare → tushare. Canada, Vietnam, Argentina
and indices had no bullet.

test_fallback_chains_are_written_in_the_order_the_loader_walks compares
every chain a README writes with _DEFAULT_CHAINS, both ways, as
sequences, so translated labels need no mapping.
This commit is contained in:
Haozhe Wu committed 2026-09-29 17:22:36 +08:00
1 parent 8a6d1934bc
commit 36485bf55b
8 files changed
+69 -14

No files matched your search

+4 -2
View File
@@ -582,8 +582,10 @@ One `get_market_data` call, **28 market-data sources**, one of them the optional
- **India (NSE/BSE)** → `yahoo` · `yfinance` · `india_broker` · `local`
- **Korea (KOSPI/KOSDAQ)** → `pykrx` · `yahoo` · `yfinance` · `local`
- **UK (LSE)** → `yahoo` · `yfinance` · `local` *(declared GBP/GBp quotes only)*
- **Crypto** → `okx` · `ccxt` · `binance` · `yfinance` · `local`
- **Forex / metals** → `mt5` · `yfinance` · `akshare` · `local`  ·  *(futures / fund / macro → `tushare`/`akshare` → `local`)*
- **Crypto** → `okx` · `binance` · `ccxt` · `yfinance` · `local`
- **Forex / metals** → `mt5` · `akshare` · `yfinance` · `local`
- **Canada / Vietnam / Argentina / indices** → `yahoo` · `yfinance` · `local`
- **China futures** → `akshare` · `local`  ·  **funds** → `tushare` · `akshare` · `local`  ·  **macro** → `akshare` · `tushare` · `local`
### Using Longbridge explicitly
+4 -2
View File
@@ -469,8 +469,10 @@ vibe-trading connector install /tmp/my-broker
- **أسهم الهند (NSE/BSE)** → `yahoo` · `yfinance` · `india_broker` · `local`
- **كوريا (KOSPI/KOSDAQ)** → `pykrx` · `yahoo` · `yfinance` · `local`
- **المملكة المتحدة (LSE)** → `yahoo` · `yfinance` · `local` *(الأسعار المعلنة بـ GBP/GBp فقط)*
- **الكريبتو** → `okx` · `ccxt` · `binance` · `yfinance` · `local`
- **الفوركس / المعادن** → `mt5` · `yfinance` · `akshare` · `local`  ·  *(العقود الآجلة / الصناديق / الاقتصاد الكلي → `tushare`/`akshare` → `local`)*
- **الكريبتو** → `okx` · `binance` · `ccxt` · `yfinance` · `local`
- **الفوركس / المعادن** → `mt5` · `akshare` · `yfinance` · `local`
- **كندا / فيتنام / الأرجنتين / المؤشرات** → `yahoo` · `yfinance` · `local`
- **العقود الآجلة الصينية** → `akshare` · `local`  ·  **الصناديق** → `tushare` · `akshare` · `local`  ·  **الاقتصاد الكلي** → `akshare` · `tushare` · `local`
### استخدام Longbridge صراحةً
+4 -2
View File
@@ -468,8 +468,10 @@ Una sola llamada `get_market_data`, **28 fuentes de datos de mercado**, una de e
- **India (NSE/BSE)** → `yahoo` · `yfinance` · `india_broker` · `local`
- **Corea (KOSPI/KOSDAQ)** → `pykrx` · `yahoo` · `yfinance` · `local`
- **Reino Unido (LSE)** → `yahoo` · `yfinance` · `local` *(solo cotizaciones declaradas en GBP/GBp)*
- **Cripto** → `okx` · `ccxt` · `binance` · `yfinance` · `local`
- **Forex / metales** → `mt5` · `yfinance` · `akshare` · `local`  ·  *(futuros / fondos / macro → `tushare`/`akshare` → `local`)*
- **Cripto** → `okx` · `binance` · `ccxt` · `yfinance` · `local`
- **Forex / metales** → `mt5` · `akshare` · `yfinance` · `local`
- **Canadá / Vietnam / Argentina / índices** → `yahoo` · `yfinance` · `local`
- **Futuros de China** → `akshare` · `local`  ·  **fondos** → `tushare` · `akshare` · `local`  ·  **macro** → `akshare` · `tushare` · `local`
### Uso explícito de Longbridge
+4 -2
View File
@@ -630,8 +630,10 @@ Satu call `get_market_data`, **28 sumber data market**, salah satunya marketplac
- **India (NSE/BSE)** → `yahoo` · `yfinance` · `india_broker` · `local`
- **Korea (KOSPI/KOSDAQ)** → `pykrx` · `yahoo` · `yfinance` · `local`
- **UK (LSE)** → `yahoo` · `yfinance` · `local` *(declared GBP/GBp quotes only)*
- **Crypto** → `okx` · `ccxt` · `binance` · `yfinance` · `local`
- **Forex / metals** → `mt5` · `yfinance` · `akshare` · `local`  ·  *(futures / fund / macro → `tushare`/`akshare` → `local`)*
- **Crypto** → `okx` · `binance` · `ccxt` · `yfinance` · `local`
- **Forex / metals** → `mt5` · `akshare` · `yfinance` · `local`
- **Canada / Vietnam / Argentina / indices** → `yahoo` · `yfinance` · `local`
- **China futures** → `akshare` · `local`  ·  **funds** → `tushare` · `akshare` · `local`  ·  **macro** → `akshare` · `tushare` · `local`
### Menggunakan Longbridge secara eksplisit
+4 -2
View File
@@ -469,8 +469,10 @@ vibe-trading connector install /tmp/my-broker
- **インド株(NSE/BSE)** → `yahoo` · `yfinance` · `india_broker` · `local`
- **韓国(KOSPI/KOSDAQ)** → `pykrx` · `yahoo` · `yfinance` · `local`
- **英国(LSE)** → `yahoo` · `yfinance` · `local` *(GBP/GBp と明示されたクォートのみ)*
- **暗号資産** → `okx` · `ccxt` · `binance` · `yfinance` · `local`
- **為替/貴金属** → `mt5` · `yfinance` · `akshare` · `local`  ·  *(先物 / ファンド / マクロ → `tushare`/`akshare` → `local`)*
- **暗号資産** → `okx` · `binance` · `ccxt` · `yfinance` · `local`
- **為替/貴金属** → `mt5` · `akshare` · `yfinance` · `local`
- **カナダ / ベトナム / アルゼンチン / 指数** → `yahoo` · `yfinance` · `local`
- **中国先物** → `akshare` · `local`  ·  **ファンド** → `tushare` · `akshare` · `local`  ·  **マクロ** → `akshare` · `tushare` · `local`
### Longbridge を明示的に使う
+4 -2
View File
@@ -469,8 +469,10 @@ vibe-trading connector install /tmp/my-broker
- **인도 (NSE/BSE)** → `yahoo` · `yfinance` · `india_broker` · `local`
- **한국 (KOSPI/KOSDAQ)** → `pykrx` · `yahoo` · `yfinance` · `local`
- **영국 (LSE)** → `yahoo` · `yfinance` · `local` *(명시된 GBP/GBp 호가만 허용)*
- **크립토** → `okx` · `ccxt` · `binance` · `yfinance` · `local`
- **외환/귀금속** → `mt5` · `yfinance` · `akshare` · `local`  ·  *(선물 / 펀드 / 매크로 → `tushare`/`akshare` → `local`)*
- **크립토** → `okx` · `binance` · `ccxt` · `yfinance` · `local`
- **외환/귀금속** → `mt5` · `akshare` · `yfinance` · `local`
- **캐나다 / 베트남 / 아르헨티나 / 지수** → `yahoo` · `yfinance` · `local`
- **중국 선물** → `akshare` · `local`  ·  **펀드** → `tushare` · `akshare` · `local`  ·  **매크로** → `akshare` · `tushare` · `local`
### Longbridge를 명시적으로 사용하기
+4 -2
View File
@@ -484,8 +484,10 @@ vibe-trading connector install /tmp/my-broker
- **印度(NSE/BSE)** → `yahoo` · `yfinance` · `india_broker` · `local`
- **韩国(KOSPI/KOSDAQ)** → `pykrx` · `yahoo` · `yfinance` · `local`
- **英国(LSE)** → `yahoo` · `yfinance` · `local` *(仅接受明示为 GBP/GBp 的报价)*
- **加密** → `okx` · `ccxt` · `binance` · `yfinance` · `local`
- **外汇 / 贵金属** → `mt5` · `yfinance` · `akshare` · `local`  ·  *(期货 / 基金 / 宏观 → `tushare`/`akshare` → `local`)*
- **加密** → `okx` · `binance` · `ccxt` · `yfinance` · `local`
- **外汇 / 贵金属** → `mt5` · `akshare` · `yfinance` · `local`
- **加拿大 / 越南 / 阿根廷 / 指数** → `yahoo` · `yfinance` · `local`
- **国内期货** → `akshare` · `local`  ·  **基金** → `tushare` · `akshare` · `local`  ·  **宏观** → `akshare` · `tushare` · `local`
### 显式使用长桥
+41
View File
@@ -678,3 +678,44 @@ def test_repo_tree_states_the_real_engine_count(readme: str) -> None:
f"{readme}: engines tree line says {match.group('count')}, "
f"the code ships {_engine_count() - 1} plus the composite engine"
)
# A fallback-chain bullet: "- **<label>** → `a` · `b` · …". The label is
# translated, so the chains are matched as sequences, not by market name.
_CHAIN_LINE_RE = re.compile(r"^- \*\*[^*\n]+\*\* → `")
_CHAIN_RUN_RE = re.compile(r"→ ((?:`[a-z0-9_]+`(?: · )?)+)")
def _readme_chains(name: str) -> set[tuple[str, ...]]:
"""Return every fallback chain a README's bullet list writes out.
Args:
name: README file name relative to the repository root.
Returns:
Each chain as a tuple of source names, in the order written.
"""
chains = set()
for line in _read(name).splitlines():
if _CHAIN_LINE_RE.match(line):
for run in _CHAIN_RUN_RE.findall(line):
chains.add(tuple(re.findall(r"`([a-z0-9_]+)`", run)))
return chains
@pytest.mark.parametrize("readme", READMES)
def test_fallback_chains_are_written_in_the_order_the_loader_walks(readme: str) -> None:
"""The bullet list is the order ``source: "auto"`` tries sources in.
Crypto read okx · ccxt · binance and forex mt5 · yfinance · akshare for
months while the loader walked binance before ccxt and akshare before
yfinance. Checked both ways against the default chains: a written chain the
loader never walks is wrong, and a chain the loader walks that no bullet
shows is missing.
"""
from backtest.loaders.registry import _DEFAULT_CHAINS
code = {tuple(chain) for chain in _DEFAULT_CHAINS.values()}
written = _readme_chains(readme)
assert not written - code, f"{readme}: chains the loader does not walk: {sorted(written - code)}"
assert not code - written, f"{readme}: chains the loader walks but the README omits: {sorted(code - written)}"