Bug: Tabular extraction misses bare \data: [...]\ arrays → K-line DataFrame becomes single cell
Environment
- Repo: FTShare-python-sdk
- File: \src/ftshare/response.py\ (\extract_tabular)
Repro
\\python
import ftshare as ft
m = ft.market_api(timeout=20)
df = m.daec_ohlcs(symbol="600000.XSHG", since="20240101", until="20240131")
print(df.shape) # (1, 3) ← expected (N, 7) with open/high/low/close/volume...
print(df.columns) # ['code', 'message', 'data']
print(type(df['data'].iloc[0])) # list — all 22 K-lines stuffed into one cell
\\
Root cause
\extract_tabular\ only handles three shapes:
- {"data": {"records": [...]}}\
- {"data": {"items": [...]}}\
- {"items": [...]}\
But this endpoint (and likely others) returns {"code": 200, "message": "success", "data": [...]}\ — \data\ is a plain list, not wrapped in
ecords/\items. extract_tabular returns the payload unchanged, so the DataFrame layer renders code/message/data as columns and the array lands in a single cell.
aw=True works fine (data is a 22-element list), confirming server-side data is correct.
Suggested fix
Add a bare-array branch:
\\python
if isinstance(data, list):
return data
\
placed after the existing data.records / data.items checks (before the final fallback). Consider a quick scan of other endpoints returning top-level data arrays to confirm scope.
Tested 2026-08-15 against the live gateway.
Bug: Tabular extraction misses bare \data: [...]\ arrays → K-line DataFrame becomes single cell
Environment
Repro
\\python
import ftshare as ft
m = ft.market_api(timeout=20)
df = m.daec_ohlcs(symbol="600000.XSHG", since="20240101", until="20240131")
print(df.shape) # (1, 3) ← expected (N, 7) with open/high/low/close/volume...
print(df.columns) # ['code', 'message', 'data']
print(type(df['data'].iloc[0])) # list — all 22 K-lines stuffed into one cell
\\
Root cause
\extract_tabular\ only handles three shapes:
But this endpoint (and likely others) returns {"code": 200, "message": "success", "data": [...]}\ — \data\ is a plain list, not wrapped in
ecords/\items. extract_tabular returns the payload unchanged, so the DataFrame layer renders code/message/data as columns and the array lands in a single cell.
aw=True works fine (data is a 22-element list), confirming server-side data is correct.
Suggested fix
Add a bare-array branch:
\\python
if isinstance(data, list):
return data
\
placed after the existing data.records / data.items checks (before the final fallback). Consider a quick scan of other endpoints returning top-level data arrays to confirm scope.
Tested 2026-08-15 against the live gateway.