在全球金融市场中,美股(纳斯达克、纽交所)作为规模最大、流动性最强的市场,一直是量化交易和金融应用开发的核心关注点。对于开发者而言,高效、稳定地获取美股实时行情和历史K线数据,是构建投资分析工具、量化策略和行情应用的基础。
本文将从技术实践角度出发,详细介绍如何通过脉动行情数据接口对接美股市场数据,重点实现实时行情获取和K线数据查询两个核心功能。我们将通过完整的Python代码示例,帮助开发者快速掌握美股数据对接的技术要点。
一、美股数据对接基础
1.1 接口概述
脉动行情数据接口提供覆盖全球多市场的实时金融数据,包括美股、港股、A股、期货、外汇、数字货币等品种-1。其美股数据具有以下特点:
-
市场覆盖:纳斯达克(NASDAQ)、纽交所(NYSE)等美国主要交易所-2
-
接入方式:支持WebSocket实时推送和HTTP REST接口两种方式-4
-
数据内容:实时行情、历史K线、盘口深度、实时成交等
-
技术优势:毫秒级延迟、自动断线重连、多产品合并订阅-4
1.2 接入前准备
在开始对接之前,需要完成以下准备工作:
官网:http://39.107.99.235:1008/market
1.3 基础配置与请求封装
# config.py – 配置文件
import requests
import json
import time
from typing import Optional, Dict, Any
# 脉动行情API基础配置
PULSE_CONFIG = {
'base_url': 'http://39.107.99.235:1008', # API基础地址
'ws_url': 'ws://39.107.99.235/ws', # WebSocket地址
'headers': {
'User-Agent': 'Mozilla/5.0 (compatible; PulseDataClient/1.0)',
'Accept-Encoding': 'gzip' # 启用gzip压缩,响应速度更快
},
'timeout': 10
}
class PulseDataClient:
"""脉动数据API客户端基础类"""
def __init__(self):
self.base_url = PULSE_CONFIG['base_url']
self.session = requests.Session()
self.session.headers.update(PULSE_CONFIG['headers'])
def _make_request(self, endpoint: str, params: Dict[str, Any]) -> Optional[Dict]:
"""
通用请求方法,包含重试机制和gzip解压
"""
max_retries = 3
for attempt in range(max_retries):
try:
response = self.session.get(
f"{self.base_url}{endpoint}",
params=params,
timeout=PULSE_CONFIG['timeout']
)
if response.status_code == 200:
# 处理gzip压缩的响应
data = response.json()
return data
elif response.status_code == 429:
# 频率限制,等待后重试
wait_time = (attempt + 1) * 2
print(f"请求频率超限,等待{wait_time}秒后重试…")
time.sleep(wait_time)
continue
else:
print(f"HTTP错误 {response.status_code}")
return None
except requests.exceptions.RequestException as e:
print(f"请求失败 (尝试 {attempt+1}/{max_retries}): {e}")
if attempt < max_retries – 1:
time.sleep(2 ** attempt) # 指数退避
return None
二、获取美股实时行情数据
实时行情是金融应用的核心数据。脉动数据提供HTTP接口方式获取实时行情
2.1 实时行情接口实现
# realtime_quote.py – 实时行情模块
from config import PulseDataClient
from typing import List, Dict, Optional
class USStockQuote(PulseDataClient):
"""美股实时行情查询类"""
def get_quote(self, code: str) -> Optional[Dict]:
"""
获取单只美股实时行情
Args:
code: 产品代码,如 'AAPL' (苹果), 'MSFT' (微软), 'TSLA' (特斯拉)
Returns:
行情数据字典
"""
endpoint = "/getQuote.php"
params = {'code': code}
response = self._make_request(endpoint, params)
if response and response.get('code') == 200:
return response.get('data')
else:
print(f"获取{code}行情失败: {response.get('msg') if response else '未知错误'}")
return None
def get_multiple_quotes(self, codes: List[str]) -> Dict[str, Optional[Dict]]:
"""
获取多只美股实时行情(注意频率限制)
Args:
codes: 产品代码列表
Returns:
代码到行情数据的映射字典
"""
results = {}
for code in codes:
# 注意频率限制:每个产品每秒最多3次
results[code] = self.get_quote(code)
time.sleep(0.35) # 控制请求频率,约每秒3个
return results
def parse_quote_data(self, data: Dict) -> Dict:
"""
解析行情数据,提取关键字段
Args:
data: get_quote返回的原始数据
Returns:
结构化行情数据
"""
if not data or 'body' not in data:
return {}
body = data['body']
# 基础行情字段
quote = {
'code': body.get('StockCode'), # 产品代码
'price': body.get('Price'), # 最新价
'open': body.get('Open'), # 当日开盘价
'high': body.get('High'), # 当日最高价
'low': body.get('Low'), # 当日最低价
'last_close': body.get('LastClose'), # 昨日收盘价
'time': body.get('Time'), # 更新时间
'timestamp': body.get('LastTime'), # 更新时间戳
'volume': body.get('TotalVol'), # 当日成交量
'diff': data.get('Diff'), # 涨跌额
'diff_rate': data.get('DiffRate') # 涨跌幅
}
# 盘口深度数据(买1-5档)
if 'Depth' in body:
depth = body['Depth']
# 买单盘口
if 'Buy' in depth and depth['Buy']:
quote['bids'] = []
for i, bid in enumerate(depth['Buy'][:5]): # 取前5档
quote['bids'].append({
'price': bid.get(f'BP{i+1}'),
'size': bid.get(f'BV{i+1}')
})
# 卖单盘口
if 'Sell' in depth and depth['Sell']:
quote['asks'] = []
for i, ask in enumerate(depth['Sell'][:5]): # 取前5档
quote['asks'].append({
'price': ask.get(f'SP{i+1}'),
'size': ask.get(f'SV{i+1}')
})
# 实时成交明细
if 'BS' in body and body['BS']:
quote['trades'] = []
for trade in body['BS'][:10]: # 取最近10笔
quote['trades'].append({
'time': trade.get('time'),
'price': trade.get('price'),
'size': trade.get('size'),
'direction': trade.get('direction') # 1:卖, 2:买
})
return quote
# 使用示例
def demo_us_stock_quote():
"""美股实时行情查询示例"""
client = USStockQuote()
# 查询苹果公司行情
print("=== 苹果公司(AAPL)实时行情 ===")
data = client.get_quote('aapl')
if data:
quote = client.parse_quote_data(data)
print(f"股票代码: {quote['code']}")
print(f"最新价: ${quote['price']}")
print(f"开盘价: ${quote['open']}")
print(f"最高价: ${quote['high']}")
print(f"最低价: ${quote['low']}")
print(f"成交量: {quote['volume']}")
print(f"涨跌幅: {quote['diff_rate']}%")
print(f"更新时间: {quote['time']}")
# 打印盘口数据
if 'bids' in quote and quote['bids']:
print("\\n买盘(前5档):")
for i, bid in enumerate(quote['bids']):
if bid['price']:
print(f" 买{i+1}: ${bid['price']} @ {bid['size']}")
if 'asks' in quote and quote['asks']:
print("\\n卖盘(前5档):")
for i, ask in enumerate(quote['asks']):
if ask['price']:
print(f" 卖{i+1}: ${ask['price']} @ {ask['size']}")
# 打印最近成交
if 'trades' in quote and quote['trades']:
print("\\n最近成交:")
for trade in quote['trades'][:3]:
direction = "买入" if trade['direction'] == 2 else "卖出"
print(f" {trade['time']} ${trade['price']} {trade['size']} {direction}")
# 查询多只股票(特斯拉、微软)
print("\\n=== 多只股票批量查询 ===")
symbols = ['tsla', 'msft']
results = client.get_multiple_quotes(symbols)
for symbol, data in results.items():
if data:
quote = client.parse_quote_data(data)
print(f"{symbol.upper()}: ${quote['price']} ({quote['diff_rate']}%)")
if __name__ == "__main__":
demo_us_stock_quote()
2.2 字段说明
| StockCode | 产品代码 | AAPL |
| Price | 最新价 | 175.34 |
| Open | 当日开盘价 | 174.50 |
| High | 当日最高价 | 176.20 |
| Low | 当日最低价 | 174.10 |
| LastClose | 昨日收盘价 | 173.80 |
| TotalVol | 当日成交量 | 52436700 |
| Diff | 涨跌额 | +1.54 |
| DiffRate | 涨跌幅 | +0.89% |
| BP1/BV1 | 买一价/量 | 175.33 / 100 |
| SP1/SV1 | 卖一价/量 | 175.35 / 200 |
三、获取美股K线数据
K线数据是技术分析和策略回测的基础。脉动数据提供HTTP接口获取历史K线,支持多种时间周期-4。
3.1 K线数据接口实现
# kline_data.py – K线数据模块
from config import PulseDataClient
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime
from typing import List, Optional
class USStockKLine(PulseDataClient):
"""美股K线数据查询类"""
# 时间周期映射
TIME_FRAMES = {
'1m': '1分钟',
'5m': '5分钟',
'15m': '15分钟',
'30m': '30分钟',
'1h': '1小时',
'1d': '日线',
'1M': '月线'
}
# 最大条数限制
MAX_ROWS = {
'1m': 600,
'5m': 300,
'15m': 300,
'30m': 300,
'1h': 300,
'1d': 300,
'1M': 100
}
def get_kline(self, code: str, timeframe: str = '1d', rows: int = 100) -> Optional[List]:
"""
获取K线数据
Args:
code: 产品代码,如 'AAPL'
timeframe: 时间周期,支持 '1m','5m','15m','30m','1h','1d','1M'
rows: 获取条数,不能超过对应周期的最大限制
Returns:
K线数据列表
"""
# 参数验证
if timeframe not in self.TIME_FRAMES:
print(f"不支持的时间周期: {timeframe},支持: {list(self.TIME_FRAMES.keys())}")
return None
max_rows = self.MAX_ROWS.get(timeframe, 100)
if rows > max_rows:
print(f"警告: {timeframe}周期最大支持{max_rows}条数据,将使用{max_rows}")
rows = max_rows
endpoint = "/redis.php"
params = {
'code': code,
'time': timeframe,
'rows': rows
}
response = self._make_request(endpoint, params)
if response and isinstance(response, list):
return response
else:
print(f"获取K线数据失败")
return None
def parse_kline_data(self, raw_data: List) -> List[Dict]:
"""
解析K线原始数据
Args:
raw_data: get_kline返回的原始数据
Returns:
结构化的K线数据列表
"""
klines = []
for item in raw_data:
if len(item) >= 7:
kline = {
'timestamp': item[0], # 毫秒时间戳
'open': float(item[1]), # 开盘价
'high': float(item[2]), # 最高价
'low': float(item[3]), # 最低价
'close': float(item[4]), # 收盘价
'time_str': item[5], # 格式化时间字符串
'volume': float(item[6]) if item[6] else 0 # 成交量
}
klines.append(kline)
return klines
def kline_to_dataframe(self, klines: List[Dict]) -> pd.DataFrame:
"""
将K线数据转换为Pandas DataFrame
Args:
klines: parse_kline_data返回的结构化数据
Returns:
DataFrame格式的K线数据,包含技术指标
"""
if not klines:
return pd.DataFrame()
df = pd.DataFrame(klines)
df['datetime'] = pd.to_datetime(df['timestamp'], unit='ms')
df.set_index('datetime', inplace=True)
# 计算常用技术指标
df['ma5'] = df['close'].rolling(window=5).mean() # 5日均线
df['ma10'] = df['close'].rolling(window=10).mean() # 10日均线
df['ma20'] = df['close'].rolling(window=20).mean() # 20日均线
# 计算涨跌幅
df['pct_change'] = df['close'].pct_change() * 100
return df
def get_kline_with_indicators(self, code: str, timeframe: str = '1d',
rows: int = 100) -> Optional[pd.DataFrame]:
"""
一站式获取带技术指标的K线数据
Args:
code: 产品代码
timeframe: 时间周期
rows: 获取条数
Returns:
带技术指标的DataFrame
"""
raw_data = self.get_kline(code, timeframe, rows)
if not raw_data:
return None
parsed = self.parse_kline_data(raw_data)
df = self.kline_to_dataframe(parsed)
return df
# 使用示例
def demo_us_stock_kline():
"""美股K线数据查询示例"""
client = USStockKLine()
# 示例1: 获取特斯拉日线数据
print("=== 特斯拉(TSLA)日线数据 ===")
df = client.get_kline_with_indicators('tsla', timeframe='1d', rows=30)
if df is not None and not df.empty:
print(f"数据条数: {len(df)}")
print("\\n最新5条数据:")
print(df[['open', 'high', 'low', 'close', 'volume', 'pct_change']].tail())
# 显示最新K线
latest = df.iloc[-1]
print(f"""
最新K线 ({latest.name.strftime('%Y-%m-%d')}):
开盘: ${latest['open']:.2f}
最高: ${latest['high']:.2f}
最低: ${latest['low']:.2f}
收盘: ${latest['close']:.2f}
成交量: {latest['volume']:.0f}
涨跌幅: {latest['pct_change']:.2f}%
5日均线: ${latest['ma5']:.2f}
20日均线: ${latest['ma20']:.2f}
""")
# 示例2: 获取苹果15分钟K线(用于日内分析)
print("\\n=== 苹果(AAPL)15分钟K线 ===")
df_15m = client.get_kline_with_indicators('aapl', timeframe='15m', rows=20)
if df_15m is not None and not df_15m.empty:
print("最新3条15分钟K线:")
for idx, row in df_15m.tail(3).iterrows():
print(f"{idx.strftime('%H:%M')} 开:${row['open']:.2f} 高:${row['high']:.2f} "
f"低:${row['low']:.2f} 收:${row['close']:.2f} 涨跌:{row['pct_change']:.2f}%")
# 示例3: 获取微软60分钟K线
print("\\n=== 微软(MSFT)60分钟K线 ===")
df_1h = client.get_kline_with_indicators('msft', timeframe='1h', rows=24) # 24小时数据
if df_1h is not None and not df_1h.empty:
# 计算日内高低点
high = df_1h['high'].max()
low = df_1h['low'].min()
print(f"过去24小时最高: ${high:.2f}")
print(f"过去24小时最低: ${low:.2f}")
print(f"当前价格: ${df_1h.iloc[-1]['close']:.2f}")
if __name__ == "__main__":
demo_us_stock_kline()
六、总结
通过本文的技术实现,我们完成了脉动行情数据接口的美股数据对接,实现了两个核心功能:
实时行情获取:支持单只和多只美股的实时价格、盘口深度、成交明细等数据查询
K线数据查询:支持分钟、小时、日线等多种时间周期的历史K线获取,并集成了基础技术指标计算
脉动数据的美股接口具有以下特点-1-4:
-
市场覆盖全面:支持纳斯达克、纽交所等美国主要交易所
-
数据内容丰富:不仅包含基础行情,还有盘口深度和实时成交
-
接入方式灵活:本文仅实现了HTTP接口,实际还支持WebSocket实时推送


