Add files to chanlun_1
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
"""
|
||||
数据获取模块:使用ccxt库拉取数字货币市场数据
|
||||
"""
|
||||
|
||||
import ccxt
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
from datetime import datetime, timedelta
|
||||
import time
|
||||
from typing import List, Dict, Optional, Tuple
|
||||
import logging
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DataFetcher:
|
||||
"""数据获取器:负责从交易所获取K线数据"""
|
||||
|
||||
def __init__(self, exchange_name: str = 'binance'):
|
||||
"""
|
||||
初始化数据获取器
|
||||
|
||||
Args:
|
||||
exchange_name: 交易所名称,默认为binance
|
||||
"""
|
||||
self.exchange_name = exchange_name
|
||||
self.exchange = self._init_exchange()
|
||||
|
||||
def _init_exchange(self) -> ccxt.Exchange:
|
||||
"""初始化交易所连接"""
|
||||
try:
|
||||
exchange_class = getattr(ccxt, self.exchange_name)
|
||||
exchange = exchange_class({
|
||||
'apiKey': '', # 对于公开数据不需要API密钥
|
||||
'secret': '',
|
||||
'timeout': 30000,
|
||||
'enableRateLimit': True,
|
||||
})
|
||||
return exchange
|
||||
except Exception as e:
|
||||
logger.error(f"初始化交易所失败: {e}")
|
||||
raise
|
||||
|
||||
def fetch_klines(self,
|
||||
symbol: str,
|
||||
timeframe: str = '1h',
|
||||
limit: int = 1000,
|
||||
since: Optional[int] = None) -> pd.DataFrame:
|
||||
"""
|
||||
获取K线数据
|
||||
|
||||
Args:
|
||||
symbol: 交易对符号,如'BTC/USDT'
|
||||
timeframe: 时间周期,如'1h', '4h', '1d'
|
||||
limit: 获取的K线数量
|
||||
since: 开始时间戳(毫秒)
|
||||
|
||||
Returns:
|
||||
包含K线数据的DataFrame
|
||||
"""
|
||||
try:
|
||||
logger.info(f"正在获取 {symbol} {timeframe} 数据,数量: {limit}")
|
||||
|
||||
# 获取原始数据
|
||||
ohlcv = self.exchange.fetch_ohlcv(
|
||||
symbol=symbol,
|
||||
timeframe=timeframe,
|
||||
limit=limit,
|
||||
since=since
|
||||
)
|
||||
|
||||
if not ohlcv:
|
||||
raise ValueError("未获取到数据")
|
||||
|
||||
# 转换为DataFrame
|
||||
df = pd.DataFrame(ohlcv, columns=[
|
||||
'timestamp', 'open', 'high', 'low', 'close', 'volume'
|
||||
])
|
||||
|
||||
# 转换时间戳为datetime
|
||||
df['datetime'] = pd.to_datetime(df['timestamp'], unit='ms')
|
||||
df.set_index('datetime', inplace=True)
|
||||
|
||||
# 确保数据类型正确
|
||||
price_columns = ['open', 'high', 'low', 'close']
|
||||
df[price_columns] = df[price_columns].astype(float)
|
||||
df['volume'] = df['volume'].astype(float)
|
||||
|
||||
logger.info(f"成功获取 {len(df)} 条K线数据")
|
||||
return df
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"获取K线数据失败: {e}")
|
||||
raise
|
||||
|
||||
def fetch_multiple_timeframes(self,
|
||||
symbol: str,
|
||||
timeframes: List[str],
|
||||
limit: int = 1000) -> Dict[str, pd.DataFrame]:
|
||||
"""
|
||||
获取多个时间周期的数据
|
||||
|
||||
Args:
|
||||
symbol: 交易对符号
|
||||
timeframes: 时间周期列表
|
||||
limit: 每个周期获取的数量
|
||||
|
||||
Returns:
|
||||
字典,键为时间周期,值为对应的DataFrame
|
||||
"""
|
||||
result = {}
|
||||
|
||||
for timeframe in timeframes:
|
||||
try:
|
||||
df = self.fetch_klines(symbol, timeframe, limit)
|
||||
result[timeframe] = df
|
||||
|
||||
# 避免请求过于频繁
|
||||
time.sleep(self.exchange.rateLimit / 1000)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"获取 {timeframe} 数据失败: {e}")
|
||||
continue
|
||||
|
||||
return result
|
||||
|
||||
def get_latest_price(self, symbol: str) -> float:
|
||||
"""
|
||||
获取最新价格
|
||||
|
||||
Args:
|
||||
symbol: 交易对符号
|
||||
|
||||
Returns:
|
||||
最新价格
|
||||
"""
|
||||
try:
|
||||
ticker = self.exchange.fetch_ticker(symbol)
|
||||
return float(ticker['last'])
|
||||
except Exception as e:
|
||||
logger.error(f"获取最新价格失败: {e}")
|
||||
raise
|
||||
|
||||
def validate_symbol(self, symbol: str) -> bool:
|
||||
"""
|
||||
验证交易对是否有效
|
||||
|
||||
Args:
|
||||
symbol: 交易对符号
|
||||
|
||||
Returns:
|
||||
是否有效
|
||||
"""
|
||||
try:
|
||||
markets = self.exchange.load_markets()
|
||||
return symbol in markets
|
||||
except Exception as e:
|
||||
logger.error(f"验证交易对失败: {e}")
|
||||
return False
|
||||
Reference in New Issue
Block a user