diff --git a/tushare/src/storage.py b/tushare/src/storage.py index c3ca757..a348116 100644 --- a/tushare/src/storage.py +++ b/tushare/src/storage.py @@ -68,6 +68,11 @@ def save_candles(df: pd.DataFrame, db_url: str = DEFAULT_DB_URL): df = df.copy() df = df.where(pd.notna(df), None) records = df.to_dict(orient="records") + # pandas float 列的 None 会被转为 NaN,需手动清理后再存入数据库 + for record in records: + for key, val in record.items(): + if isinstance(val, float) and val != val: # NaN != NaN + record[key] = None with conn.cursor() as cur: cur.executemany( """ diff --git a/web/backend/internal/store/futures.go b/web/backend/internal/store/futures.go index da8b100..8fb4480 100644 --- a/web/backend/internal/store/futures.go +++ b/web/backend/internal/store/futures.go @@ -149,9 +149,11 @@ func (s *FuturesStore) ListCandles(tsCode, start, end string) ([]Candle, error) return nil, ErrMissingTsCode } q := `SELECT ts_code, trade_date, - COALESCE(open, 0), COALESCE(high, 0), COALESCE(low, 0), COALESCE(close, 0), - COALESCE(vol, 0), COALESCE(amount, 0), - COALESCE(oi, 0), COALESCE(oi_chg, 0), COALESCE(pre_close, 0) + COALESCE(NULLIF(open, 'NaN'::real), 0), COALESCE(NULLIF(high, 'NaN'::real), 0), + COALESCE(NULLIF(low, 'NaN'::real), 0), COALESCE(NULLIF(close, 'NaN'::real), 0), + COALESCE(NULLIF(vol, 'NaN'::real), 0), COALESCE(NULLIF(amount, 'NaN'::real), 0), + COALESCE(NULLIF(oi, 'NaN'::real), 0), COALESCE(NULLIF(oi_chg, 'NaN'::real), 0), + COALESCE(NULLIF(pre_close, 'NaN'::real), 0) FROM candles WHERE ts_code = $1` args := []any{tsCode} n := 1