Python对接期货市场API对接实现指南

58 阅读4分钟

本文将详细介绍如何使用Python对接StockTV期货市场API,并提供完整的代码示例和最佳实践。

一、环境准备

1.1 安装依赖

pip install requests websocket-client pandas numpy

1.2 获取API Key

联系官方获取密钥:Telegram @CryptoRzz

二、基础配置

import requests
import json
import websocket
import threading
import time

# API配置
API_KEY = "YOUR_API_KEY"  # 替换为实际API密钥
BASE_URL = "https://api.stocktv.top"
WS_URL = "wss://ws-api.stocktv.top"

# 期货品种映射表
SYMBOL_MAP = {
    "CL": "WTI原油",
    "GC": "黄金",
    "SI": "白银",
    "NG": "天然气",
    "ZS": "大豆",
    "ZC": "玉米",
    "HG": "铜"
}

# 交易所映射表
EXCHANGE_MAP = {
    "CME": "芝加哥商品交易所",
    "NYMEX": "纽约商品交易所",
    "ICE": "洲际交易所",
    "LME": "伦敦金属交易所"
}

三、REST API实现

3.1 获取期货市场列表

def get_futures_list(category=None):
    """获取期货市场列表"""
    url = f"{BASE_URL}/futures/list"
    params = {"key": API_KEY}
    if category:
        params["category"] = category
    
    try:
        response = requests.get(url, params=params)
        if response.status_code == 200:
            data = response.json()
            if data["code"] == 200:
                print("期货市场列表获取成功:")
                for item in data["data"]:
                    print(f"{SYMBOL_MAP.get(item['symbol'], item['symbol'])} "
                          f"({item['symbol']}) - {EXCHANGE_MAP.get(item['exchange'], item['exchange'])}: "
                          f"最新价 {item['lastPrice']}, 涨跌 {item['change']} ({item['changePercent']}%)")
            else:
                print(f"API返回错误: {data['message']}")
        else:
            print(f"请求失败,状态码: {response.status_code}")
    except Exception as e:
        print(f"获取期货列表时发生错误: {str(e)}")

# 示例:获取能源类期货
get_futures_list(category="energy")

3.2 查询指定期货行情

def get_futures_quote(symbol):
    """获取指定期货行情"""
    url = f"{BASE_URL}/futures/querySymbol"
    params = {"key": API_KEY, "symbol": symbol}
    
    try:
        response = requests.get(url, params=params)
        if response.status_code == 200:
            data = response.json()
            if data["code"] == 200:
                quote = data["data"]
                print(f"\n{symbol} ({SYMBOL_MAP.get(symbol, '未知品种')}) 行情:")
                print(f"交易所: {EXCHANGE_MAP.get(quote['exchange'], quote['exchange'])}")
                print(f"最新价: {quote['lastPrice']}")
                print(f"涨跌: {quote['change']} ({quote['changePercent']}%)")
                print(f"开盘: {quote['open']}, 最高: {quote['high']}, 最低: {quote['low']}")
                print(f"买一价: {quote['bid']}, 卖一价: {quote['ask']}")
                print(f"成交量: {quote['volume']}, 持仓量: {quote['openInterest']}")
                print(f"结算价: {quote['settlement']}, 前收盘: {quote['prevClose']}")
                print(f"交易时间: {quote['tradingHours']}, 到期日: {quote['expiryDate']}")
            else:
                print(f"API返回错误: {data['message']}")
        else:
            print(f"请求失败,状态码: {response.status_code}")
    except Exception as e:
        print(f"获取期货行情时发生错误: {str(e)}")

# 示例:获取WTI原油行情
get_futures_quote("CL")

3.3 获取K线数据

def get_futures_kline(symbol, interval="15m", limit=100):
    """获取期货K线数据"""
    url = f"{BASE_URL}/futures/kline"
    params = {
        "key": API_KEY,
        "symbol": symbol,
        "interval": interval,
        "limit": limit
    }
    
    try:
        response = requests.get(url, params=params)
        if response.status_code == 200:
            data = response.json()
            if data["code"] == 200:
                print(f"\n{symbol} 的K线数据 ({interval}):")
                for i, kline in enumerate(data["data"]):
                    if i < 5:  # 只显示前5条
                        timestamp = kline["timestamp"] / 1000  # 转换为秒
                        dt = time.strftime("%Y-%m-%d %H:%M", time.localtime(timestamp))
                        print(f"{dt} - 开: {kline['open']}, 高: {kline['high']}, "
                              f"低: {kline['low']}, 收: {kline['close']}, "
                              f"量: {kline['volume']}")
                print(f"...共 {len(data['data'])} 条数据")
            else:
                print(f"API返回错误: {data['message']}")
        else:
            print(f"请求失败,状态码: {response.status_code}")
    except Exception as e:
        print(f"获取K线数据时发生错误: {str(e)}")

# 示例:获取WTI原油15分钟K线
get_futures_kline("CL", interval="15m")

五、高级功能实现

5.1 数据缓存策略

from cachetools import TTLCache

class FuturesDataCache:
    def __init__(self, maxsize=100, ttl=60):
        """初始化数据缓存"""
        self.cache = TTLCache(maxsize=maxsize, ttl=ttl)
    
    def get_quote(self, symbol):
        """获取期货行情(带缓存)"""
        # 检查缓存
        if symbol in self.cache:
            return self.cache[symbol]
        
        # 从API获取
        url = f"{BASE_URL}/futures/querySymbol"
        params = {"key": API_KEY, "symbol": symbol}
        
        try:
            response = requests.get(url, params=params)
            if response.status_code == 200:
                data = response.json()
                if data["code"] == 200:
                    quote = data["data"]
                    # 更新缓存
                    self.cache[symbol] = quote
                    return quote
                else:
                    print(f"API返回错误: {data['message']}")
                    return None
            else:
                print(f"请求失败,状态码: {response.status_code}")
                return None
        except Exception as e:
            print(f"获取期货行情时发生错误: {str(e)}")
            return None

# 使用示例
cache = FuturesDataCache()
quote = cache.get_quote("CL")
if quote:
    print(f"WTI原油最新价: {quote['lastPrice']}")

5.2 实时数据处理器

class RealTimeDataProcessor:
    def __init__(self):
        self.data_buffer = {}
        self.batch_size = 10
        self.last_process_time = 0
    
    def add_data(self, symbol, data):
        """添加实时数据到缓冲区"""
        if symbol not in self.data_buffer:
            self.data_buffer[symbol] = []
        
        self.data_buffer[symbol].append(data)
        
        # 检查是否达到批处理条件
        current_time = time.time()
        if (len(self.data_buffer[symbol]) >= self.batch_size or 
            current_time - self.last_process_time > 1):
            self.process_data(symbol)
            self.last_process_time = current_time
    
    def process_data(self, symbol):
        """处理缓冲区的数据"""
        if symbol not in self.data_buffer or not self.data_buffer[symbol]:
            return
        
        data_points = self.data_buffer[symbol]
        
        # 计算统计指标
        prices = [d["last"] for d in data_points]
        volumes = [d["volume"] for d in data_points]
        
        avg_price = sum(prices) / len(prices)
        max_price = max(prices)
        min_price = min(prices)
        total_volume = sum(volumes)
        
        print(f"\n{symbol} 实时数据统计 (最近 {len(data_points)} 个更新):")
        print(f"平均价格: {avg_price:.2f}, 最高: {max_price:.2f}, 最低: {min_price:.2f}")
        print(f"总成交量: {total_volume}")
        
        # 清空缓冲区
        self.data_buffer[symbol] = []

# 修改WebSocket客户端的on_message方法
def on_message(self, ws, message):
    try:
        data = json.loads(message)
        
        if "channel" in data:
            symbol = data["channel"].split(":")[1]
            quote = data["data"]
            
            # 添加到实时数据处理器
            processor.add_data(symbol, {
                "last": quote["last"],
                "volume": quote["volume"],
                "timestamp": quote["timestamp"]
            })
    except Exception as e:
        print(f"处理实时数据时出错: {str(e)}")

# 初始化实时数据处理器
processor = RealTimeDataProcessor()

官方API文档:stocktv.top/

技术支持:support@stocktv.top