feat(datasource): 加密货币数据支持分钟级时间精度
- flask_server.py: dataframe_to_json 增加 asset_type 参数,crypto 使用 '%Y-%m-%d %H:%M:%S' 格式 - ccxt_source.py: 移除 normalize() 调用,保留完整时间精度 - ETF/指数数据保持天级精度 '%Y-%m-%d' 不变
This commit is contained in:
@@ -250,10 +250,14 @@ class CCXTSource:
|
||||
return None
|
||||
|
||||
df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
|
||||
|
||||
# 转换时间戳为日期索引(UTC -> 北京时间)
|
||||
# 注意:保留完整时间精度(包括分钟),用于分钟级 K 线数据
|
||||
df['date'] = pd.to_datetime(df['timestamp'], unit='ms', utc=True).dt.tz_convert('Asia/Shanghai')
|
||||
df = df.set_index('date')
|
||||
df = df[['open', 'high', 'low', 'close', 'volume']]
|
||||
df.index = df.index.normalize()
|
||||
|
||||
# 注意:不再使用 normalize(),保留完整时间精度
|
||||
|
||||
return df
|
||||
|
||||
|
||||
@@ -266,7 +266,7 @@ def fetch_data_with_ttl(
|
||||
df = f.fetch(code, start, end, timeframe=timeframe)
|
||||
if df is None or len(df) == 0:
|
||||
return None, False
|
||||
result = dataframe_to_json(df)
|
||||
result = dataframe_to_json(df, asset_type.value)
|
||||
result['code'] = code
|
||||
result['asset_type'] = asset_type.value
|
||||
result['cache_strategy'] = 'no_cache_crypto'
|
||||
@@ -369,9 +369,15 @@ class JSONEncoder(json.JSONEncoder):
|
||||
return super().default(obj)
|
||||
|
||||
|
||||
def dataframe_to_json(df: pd.DataFrame) -> Dict:
|
||||
def dataframe_to_json(df: pd.DataFrame, asset_type: Optional[str] = None) -> Dict:
|
||||
"""将 DataFrame 转换为 JSON 可序列化的字典
|
||||
|
||||
Args:
|
||||
df: DataFrame 数据
|
||||
asset_type: 资产类型,用于决定日期格式精度
|
||||
- crypto: 使用分钟级格式 '%Y-%m-%d %H:%M:%S'
|
||||
- 其他: 使用天级格式 '%Y-%m-%d'
|
||||
|
||||
如果 df.attrs 中有 info 字段,会放到最外层返回
|
||||
"""
|
||||
if df is None or len(df) == 0:
|
||||
@@ -384,12 +390,16 @@ def dataframe_to_json(df: pd.DataFrame) -> Dict:
|
||||
# 重置索引
|
||||
df_reset = df.reset_index()
|
||||
|
||||
# 处理日期列
|
||||
# 处理日期列 - 根据资产类型决定格式精度
|
||||
date_columns = ['date', 'Date', 'index', 'trade_date', 'datetime']
|
||||
|
||||
# 加密货币使用分钟级格式,其他使用天级格式
|
||||
date_format = '%Y-%m-%d %H:%M:%S' if asset_type == 'crypto' else '%Y-%m-%d'
|
||||
|
||||
for col in date_columns:
|
||||
if col in df_reset.columns:
|
||||
try:
|
||||
df_reset[col] = pd.to_datetime(df_reset[col]).dt.strftime('%Y-%m-%d')
|
||||
df_reset[col] = pd.to_datetime(df_reset[col]).dt.strftime(date_format)
|
||||
if col != 'date':
|
||||
df_reset = df_reset.rename(columns={col: 'date'})
|
||||
break
|
||||
@@ -412,8 +422,8 @@ def dataframe_to_json(df: pd.DataFrame) -> Dict:
|
||||
"count": len(records),
|
||||
"columns": list(df_clean.columns),
|
||||
"date_range": {
|
||||
"start": df.index.min().strftime('%Y-%m-%d') if len(df) > 0 else None,
|
||||
"end": df.index.max().strftime('%Y-%m-%d') if len(df) > 0 else None,
|
||||
"start": df.index.min().strftime(date_format) if len(df) > 0 else None,
|
||||
"end": df.index.max().strftime(date_format) if len(df) > 0 else None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user