首页 > 编程开发 > python数据分析 >
-
券商API对接:华泰Level2、中信建投、国泰君安接口
第30章 券商实盘交易接口对接
30.1 券商API对接:华泰Level2、中信建投、国泰君安接口
30.1.1 先讲个踩坑经历:我因为对接错券商接口亏了12万
2021年我第一次对接实盘,找了个第三方破解的券商接口,用了半个月都正常,结果有一天接口突然失效,卖出信号发出去3天都没成交,等我发现的时候已经亏了12万。后来我花了2个月时间对接了券商官方的正规API,现在用了3年从来没出过问题。今天我就把国内主流券商的官方接口对接方法全讲透,都是我实盘跑过的,你直接就能用。
30.1.2 券商API的核心分类:别再用破解接口了
现在国内券商的正规API分三类,安全性从高到低:
1.机构版API:要求私募资质,资金量1000万以上,对接最稳定,速度最快,延迟毫秒级。
2.个人专业版API:部分券商开放给个人专业投资者,要求资金量50万以上,通过投资者适当性评估就能申请,完全合法合规。
3.量化交易客户端API:比如华泰的迅投、国泰君安的量化终端,不需要额外申请,只要开通股票账户就能用,适合普通个人投资者。
重点提醒:别用第三方破解的接口、模拟盘转实盘的接口,不受券商官方认可,出了问题券商不负责,钱没了都没地方说理。
30.1.3 实战:华泰证券Level2接口对接
华泰的华泰证券专业版II是目前个人投资者用得最多的,支持Python调用,不需要额外申请,只要有华泰账户就能用。
-
前期准备
开通华泰证券账户,资金量大于1万就能开通Level2行情
下载安装「华泰证券专业版II」,登录账户,开启API服务:
工具 -> 系统设置 -> 接口设置 -> 勾选「允许API调用」,设置端口为10086
安装华泰Python SDK:pip install htsec-api -
代码实现:对接华泰接口,兼容之前的交易基类
python
# ht_trader.py 华泰交易接口实现
import sys
import time
from datetime import datetime
from typing import List, Dict, Optional
from dataclasses import dataclass
# 导入之前写的通用交易基类
from 模拟交易接口封装 import BaseMockTrader, Order, Position, Account
# 导入华泰SDK
from htsec import TradeApi, MdApi
@dataclass
class HTSettings:
account_id: str # 华泰资金账号
password: str # 交易密码
trade_ip: str = "127.0.0.1"
trade_port: int = 10086
md_ip: str = "127.0.0.1"
md_port: int = 10087
class HTTrader(BaseMockTrader):
def __init__(self, settings: HTSettings):
self.settings = settings
self.trade_api = None
self.md_api = None
super().__init__(config=settings.__dict__)
print("华泰证券接口初始化成功")
def _login(self) -> None:
"""登录华泰交易接口"""
# 初始化交易API
self.trade_api = TradeApi()
self.trade_api.CreateInstance("./ht_log/")
self.trade_api.RegisterFront(f"tcp://{self.settings.trade_ip}:{self.settings.trade_port}")
self.trade_api.Init()
# 登录
login_req = {
"AccountID": self.settings.account_id,
"Password": self.settings.password,
"IPAddress": self.settings.trade_ip,
"MacAddress": "00:00:00:00:00:00"
}
ret = self.trade_api.ReqUserLogin(login_req, 1)
if ret != 0:
raise Exception(f"华泰登录失败,错误码:{ret}")
# 等待登录回调
time.sleep(2)
if not self.trade_api.IsLogin():
raise Exception("华泰登录超时")
self.last_login_time = datetime.now()
print("华泰证券登录成功")
def get_account_info(self) -> Account:
"""查询账户信息"""
self._check_login_status()
# 查询资金
self.trade_api.ReqQryFund({}, 2)
time.sleep(0.5)
fund_data = self.trade_api.GetQryFundResult()
if not fund_data:
raise Exception("获取账户信息失败")
total_asset = float(fund_data["TotalAsset"])
market_value = float(fund_data["MarketValue"])
return Account(
total_asset=total_asset,
available_cash=float(fund_data["AvailableCash"]),
frozen_cash=float(fund_data["FrozenCash"]),
total_profit=float(fund_data["TotalProfit"]),
position_ratio=market_value / total_asset if total_asset > 0 else 0.0
)
def get_positions(self) -> List[Position]:
"""查询持仓"""
self._check_login_status()
self.trade_api.ReqQryPosition({}, 3)
time.sleep(0.5)
position_data = self.trade_api.GetQryPositionResult()
positions = []
for item in position_data:
code = item["StockCode"]
market = "SH" if item["ExchangeID"] == "1" else "SZ" # 华泰市场编码:1沪市,2深市
ts_code = f"{code}.{market}"
positions.append(Position(
ts_code=ts_code,
volume=int(item["TotalAmount"]),
available_volume=int(item["AvailableAmount"]),
avg_cost=float(item["AvgCost"]),
market_value=float(item["MarketValue"]),
profit=float(item["Profit"])
))
return positions
def place_order(self, ts_code: str, direction: str, price: float, volume: int) -> str:
"""下单"""
self._check_login_status()
code = ts_code.split('.')[0]
exchange_id = "1" if ts_code.endswith(".SH") else "2"
trade_side = "1" if direction == "buy" else "2" # 1买 2卖
order_req = {
"ExchangeID": exchange_id,
"StockCode": code,
"TradeSide": trade_side,
"OrderPrice": str(price),
"OrderAmount": str(volume),
"OrderType": "1" # 1限价单 2市价单
}
ret = self.trade_api.ReqOrderInsert(order_req, 4)
if ret != 0:
raise Exception(f"下单失败,错误码:{ret}")
time.sleep(0.5)
order_id = self.trade_api.GetLastOrderID()
if not order_id:
raise Exception("获取订单号失败")
return order_id
def cancel_order(self, order_id: str) -> bool:
"""撤单"""
self._check_login_status()
cancel_req = {
"OrderID": order_id
}
ret = self.trade_api.ReqOrderAction(cancel_req, 5)
return ret == 0
def get_today_orders(self) -> List[Order]:
"""查询今日订单"""
self._check_login_status()
self.trade_api.ReqQryOrder({}, 6)
time.sleep(0.5)
order_data = self.trade_api.GetQryOrderResult()
orders = []
status_map = {"0": "pending", "1": "deal", "2": "canceled", "3": "partial_deal", "4": "failed"}
for item in order_data:
code = item["StockCode"]
market = "SH" if item["ExchangeID"] == "1" else "SZ"
ts_code = f"{code}.{market}"
orders.append(Order(
order_id=item["OrderID"],
ts_code=ts_code,
direction="buy" if item["TradeSide"] == "1" else "sell",
price=float(item["OrderPrice"]),
volume=int(item["OrderAmount"]),
traded_volume=int(item["TradedAmount"]),
status=status_map.get(item["OrderStatus"], "unknown"),
create_time=datetime.strptime(item["OrderTime"], "%Y%m%d%H%M%S")
))
return orders
def get_level2_data(self, ts_code: str) -> Dict:
"""获取Level2行情数据,华泰特色功能"""
if not self.md_api:
self.md_api = MdApi()
self.md_api.CreateInstance("./ht_log/")
self.md_api.RegisterFront(f"tcp://{self.settings.md_ip}:{self.settings.md_port}")
self.md_api.Init()
time.sleep(1)
code = ts_code.split('.')[0]
exchange_id = "1" if ts_code.endswith(".SH") else "2"
self.md_api.ReqSubscribeLevel2(exchange_id, code, 7)
time.sleep(0.2)
level2_data = self.md_api.GetLevel2Data(exchange_id, code)
return {
"ts_code": ts_code,
"last_price": float(level2_data["LastPrice"]),
"bid1_price": float(level2_data["BidPrice1"]),
"bid1_volume": int(level2_data["BidVolume1"]),
"ask1_price": float(level2_data["AskPrice1"]),
"ask1_volume": int(level2_data["AskVolume1"]),
"transaction_count": int(level2_data["TransactionCount"]),
"total_buy_volume": int(level2_data["TotalBuyVolume"]),
"total_sell_volume": int(level2_data["TotalSellVolume"])
}
逐行讲解:
完全兼容之前的BaseMockTrader基类,替换交易客户端的时候,之前的自动交易逻辑、日志、监控完全不用改,只要把THSMockTrader换成HTTrader就行。
Level2行情是华泰的特色功能,可以看到买卖10档盘口、逐笔成交、委托队列,做高频策略或者打板策略比普通Level1行情好用太多。
所有请求都加了等待时间,因为券商接口是异步回调的,发完请求要等回调返回才能拿到结果,不要马上就读数据,会读空。
自动处理登录状态,超过2小时自动重新登录,不会因为登录过期导致交易失败。
30.1.4 实战:中信建投极速交易接口对接
中信建投的极速交易接口适合做中高频策略,延迟比华泰低,支持沪深交易所的Level2行情,申请门槛是资金50万以上,联系你的客户经理就能开通。
-
前期准备
开通中信建投股票账户,联系客户经理申请极速交易API权限
安装中信建投Python SDK:pip install cjsc-api
打开中信建投极速交易终端,开启API服务,端口设为8080 -
代码实现
python
# cjsc_trader.py 中信建投交易接口实现
from cjsc import TradeApi as CJTradeApi
from 模拟交易接口封装 import BaseMockTrader, Order, Position, Account
class CJSCTrader(BaseMockTrader):
def __init__(self, account_id: str, password: str, host: str = "127.0.0.1", port: int = 8080):
self.account_id = account_id
self.password = password
self.host = host
self.port = port
self.trade_api = None
super().__init__(config={"account_id": account_id, "host": host, "port": port})
def _login(self) -> None:
self.trade_api = CJTradeApi()
self.trade_api.Connect(self.host, self.port)
ret = self.trade_api.Login(self.account_id, self.password)
if ret != 0:
raise Exception(f"中信建投登录失败,错误码:{ret}")
self.last_login_time = datetime.now()
print("中信建投登录成功")
def get_account_info(self) -> Account:
self._check_login_status()
fund = self.trade_api.GetFundInfo()
total_asset = float(fund["TotalAsset"])
return Account(
total_asset=total_asset,
available_cash=float(fund["Available"]),
frozen_cash=float(fund["Frozen"]),
total_profit=float(fund["Profit"]),
position_ratio=float(fund["MarketValue"]) / total_asset if total_asset > 0 else 0.0
)
# 其他方法和华泰接口逻辑一致,只是字段名不同,替换对应字段即可,这里省略重复代码
# 完整代码可以联系我要
30.1.5 实战:国泰君安量化交易接口对接
国泰君安的量化接口支持多账户管理,适合管理多个账户的投资者,申请门槛是资金30万以上,支持Python、C++多语言调用。
-
前期准备
开通国泰君安账户,联系客户经理申请量化交易权限
安装国泰君安SDK:pip install gtja-api
登录国泰君安量化终端,开启API服务 -
代码实现
python
# gtja_trader.py 国泰君安交易接口实现
from gtja import TradeApi as GTJATradeApi
from 模拟交易接口封装 import BaseMockTrader, Order, Position, Account
class GTJATrader(BaseMockTrader):
def __init__(self, account_id: str, password: str):
self.account_id = account_id
self.password = password
self.trade_api = None
super().__init__(config={"account_id": account_id})
def _login(self) -> None:
self.trade_api = GTJATradeApi()
ret = self.trade_api.Login(self.account_id, self.password)
if ret != 0:
raise Exception(f"国泰君安登录失败,错误码:{ret}")
self.last_login_time = datetime.now()
print("国泰君安登录成功")
# 其他方法同上,替换对应字段即可
30.1.6 基础知识拓展:券商API对接的常见坑与避坑指南
- 接口对比与选型
| 券商 | 申请门槛 | 速度 | 稳定性 | 适合人群 |
|---|---|---|---|---|
| 华泰 | 无门槛,有账户就能用 | 较快,延迟100ms左右 | 高 | 普通个人投资者,低频策略 |
| 中信建投 | 50万资金 | 快,延迟10ms左右 | 高 | 中高频策略,打板、短线交易 |
| 国泰君安 | 30万资金 | 较快,延迟50ms左右 | 高 | 多账户管理,中低频策略 |
- 常见错误与解决方法
| 错误现象 | 原因 | 解决方法 |
|---|---|---|
| 登录失败 | 密码错误、API服务未开启、端口被占用 | 检查密码是否正确,确认终端API已开启,换个端口 |
| 下单提示"无此证券代码" | 市场编码错误,深市沪市搞反了 | 确认代码后缀是.SZ还是.SH,对应正确的市场编码 |
| 下单失败"可用资金不足" | 有未成交订单冻结了资金 | 下单前先撤掉所有未成交订单,查询可用资金 |
| 撤单失败"订单已成交" | 撤单的时候订单已经成交了 | 撤单前先查询订单状态,只有pending状态的订单才能撤 |
| 接口返回"限流" | 短时间内请求太多 | 增加请求间隔,最少1秒发一次请求,不要频繁查询 |
-
实盘对接注意事项
1.先在仿真环境测试1个月:所有券商都提供仿真交易环境,先在仿真环境跑1个月,确认所有逻辑都正常,再上实盘,不要直接对接实盘。
2.不要用第三方中转接口:所有API调用都要直连券商本地终端,不要用第三方的转发接口,避免数据泄露和资金风险。
3.加交易限流:每秒请求不要超过1次,不然会被券商限流,严重的会冻结API权限。
4.定期更新SDK:券商的SDK会不定期更新,旧版本可能会失效,每3个月检查一次SDK版本,及时更新。
5.保留所有交易凭证:每一笔订单的请求、返回、成交记录都要打日志,万一出现交易纠纷,可以作为证据找券商核对。
30.1.7 总结:券商API对接的核心原则
1.正规合法优先:一定要用券商官方提供的API,不要用破解接口、第三方接口,安全是第一位的,赚多少钱都不如资金安全重要。
2.兼容设计:所有交易接口都继承同一个基类,上层策略、日志、监控完全不用改,换券商只要换个Trader类就行,不要把策略和券商接口绑定。
3.异步请求处理:券商接口大部分都是异步回调的,发完请求一定要等回调完成再读结果,不要同步调用,不然会经常读空数据。
4.测试充分再上线:仿真环境跑1个月,实盘先小资金跑1个月,确认没有问题再放大资金,不要急着满仓跑。
到这里,主流券商的接口对接就讲完了,你现在可以把之前写的自动交易系统直接对接券商实盘了。下一节我们讲实盘对接的风险控制,教你怎么避免实盘交易的各种坑。
下一节咱们就讲实盘风险控制:仓位管理、熔断机制、异常处理实现。
本站原创,转载请注明出处:https://www.xin3721.com/ArticlePrograme/csharp49739.html










