沪深A股Level2实时推送行情接口Python分享

量化开发离不开数据接口,沪深股票Level2实时推送行情接口api(简称Level2 API)是最重要的数据之一。实现高性能高可用网络传输的最稳定方式是建立socket连接,分享代码如下:

Python全推版

# 全推版客户端
import socket
import multiprocessing
import time
import struct
import os

# 配置地址端口用户口令
TRANS_CONF = {
	'HOST': 'x.x.x.x',
	'PORT': 9001,
	'TOKEN': 'test'
}

ORDER_CONF = {
	'HOST': 'x.x.x.x',
	'PORT': 9002,
	'TOKEN': 'test'
}

# ========================================================================================
# 获取成交数据
def get_trans(my_conf):
	# 出错重连
	for x in range(3):
		try:
			# 定义参数
			my_host = my_conf['HOST']
			my_port = my_conf['PORT']
			my_token = my_conf['TOKEN']
			# 创建TCP套接字
			client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
			# 连接服务器
			client_socket.connect((my_host, my_port))
			# 设置连接参数
			client_socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024*1024)  # 发送缓存大小为1MB(默认64KB)
			client_socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 256*1024*1024)  # 接收缓存大小为256MB(默认64KB)
			client_socket.settimeout(15)
			# 发送口令登录
			client_socket.sendall(my_token.encode("UTF-8"))
			print(f"登录成交数据服务器[{my_host}:{my_port}@{my_token}]")
			# 登录成功,会收到数据(盘中)或心跳(休市);
			# 登录失败,会收不到任何回应,并抛出超时。
			last_buffer = b'' # 存放未完整未处理的字节数据
			# 计算单笔数据大小
			format_size = struct.calcsize(">6s4IQ2B2I2s") # 网络传输数据采用大端模式,format_size = 42 bytes
			# 生成解包对象示例
			mystruct = struct.Struct(">6s4IQ2B2I2s")
			# 设置每次接收数据长度
			recv_len = int(format_size*100000)
			# =================================================================
			# 示例————输出到文件和屏幕打印笔数
			if not os.path.isfile("Sample_Trans.csv"):
				title = "本地时间, 证券代码, 成交时间, 成交编号, 成交单价, 成交数量, 成交金额, 交易方向, 交易类型, 买方委托编号, 卖方委托编号, 结束符号\n"
			else:
				title = ""
			file_object = open("Sample_Trans.csv", "a")
			file_object.write(title)
			file_object.flush() 
			# =================================================================
			# 循环接收数据
			while True:
				# 定义数据列表
				datalist = [] 
				# 接收字节数据
				buffer = client_socket.recv(recv_len)
				# 新旧数据合并
				buffer = last_buffer + buffer 
				# 计算完整笔数
				data_count = int(len(buffer)/format_size)
				# 网络传输字节序列有时并非整笔到达,需要计算最后整笔位置
				end = data_count*format_size
				# 保存未完一笔
				last_buffer = buffer[end:] 
				# 处理完整逐笔
				offset = 0
				for i in range(data_count):
					# 取一笔进行处理,每次向后移动
					data = mystruct.unpack_from(buffer, offset) # 网络传输数据采用大端模式,format_size = 42 bytes
					offset += format_size
					if data[0]==b'HEARTB': # 跳过心跳
						continue
					datalist.append(data) # 加入数据列表以供后续使用
				# print(data)
				# =================================================================
				# 用户定义如何使用数据
				# 示例————输出到文件和屏幕打印笔数
				now = time.strftime("%H:%M:%S", time.localtime(int(time.time())))
				for line in datalist:
					line = list(line)
					line[0] = line[0].decode()
					line[10] = line[10].decode()
					file_object.write(now+", "+str(line)+"\n")
				file_object.flush() 
				print(f"[{now}] 收到成交数据{len(datalist)}笔,写入文件Sample_Trans.csv")
				# =================================================================
				# time.sleep(1)
		except Exception as e:
			hourmin = int(time.strftime("%H%M", time.localtime(time.time())))
			if hourmin<910 and ("WinError" in str(e)): # 9点10分之前等待连接,之后连接不上报错
				print(f'成交数据服务等待连接...')
				time.sleep(15)
				continue
			# 关闭客户端
			client_socket.close()
			print(f"成交数据服务出错了({x+1})({e})")
			time.sleep(1)
			continue

# 获取委托数据
def get_order(my_conf):
	# 出错重连
	for x in range(3):
		try:
			# 定义参数
			my_host = my_conf['HOST']
			my_port = my_conf['PORT']
			my_token = my_conf['TOKEN']
			# 创建TCP套接字
			client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
			# 连接服务器
			client_socket.connect((my_host, my_port))
			# 设置连接参数
			client_socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024*1024)  # 发送缓存大小为1MB(默认64KB)
			client_socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 256*1024*1024)  # 接收缓存大小为256MB(默认64KB)
			client_socket.settimeout(15)
			# 发送口令登录
			client_socket.sendall(my_token.encode("UTF-8"))
			print(f"登录委托数据服务器[{my_host}:{my_port}@{my_token}]")
			# 登录成功,会收到数据(盘中)或心跳(休市);
			# 登录失败,会收不到任何回应,并抛出超时。
			last_buffer = b'' # 存放未完整未处理的字节数据
			# 计算单笔数据大小
			format_size = struct.calcsize(">6s4I2B2s") # 网络传输数据采用大端模式,format_size = 26 bytes
			# 生成解包对象示例
			mystruct = struct.Struct(">6s4I2B2s")
			# 设置每次接收数据长度
			recv_len = int(format_size*100000)
			# =================================================================
			# 示例————输出到文件和屏幕打印笔数
			if not os.path.isfile("Sample_Order.csv"):
				title = "本地时间, 证券代码, 委托时间, 委托编号, 委托单价, 委托数量, 交易方向, 交易类型, 结束符号\n"
			else:
				title = ""
			file_object = open("Sample_Order.csv", "a")
			file_object.write(title)
			file_object.flush() 
			# =================================================================
			# 循环接收数据
			while True:
				# 定义数据列表
				datalist = [] 
				# 接收字节数据
				buffer = client_socket.recv(recv_len)
				# 新旧数据合并
				buffer = last_buffer + buffer 
				# 计算完整笔数
				data_count = int(len(buffer)/format_size)
				# 网络传输字节序列有时并非整笔到达,需要计算最后整笔位置
				end = data_count*format_size
				# 保存未完一笔
				last_buffer = buffer[end:] 
				# 处理完整逐笔
				offset = 0
				for i in range(data_count):
					# 取一笔进行处理,每次向后移动
					data = mystruct.unpack_from(buffer, offset) # 网络传输数据采用大端模式,format_size = 42 bytes
					offset += format_size
					if data[0]==b'HEARTB': # 跳过心跳
						continue
					datalist.append(data) # 加入数据列表以供后续使用
				# print(data)
				# =================================================================
				# 用户定义如何使用数据
				# 示例————输出到文件和屏幕打印笔数
				now = time.strftime("%H:%M:%S", time.localtime(int(time.time())))
				for line in datalist:
					line = list(line)
					line[0] = line[0].decode()
					line[7] = line[7].decode()
					file_object.write(now+", "+str(line)+"\n")
				file_object.flush() 
				print(f"[{now}] 收到委托数据{len(datalist)}笔,写入文件Sample_Order.csv")
				# =================================================================
				# time.sleep(1)
		except Exception as e:
			hourmin = int(time.strftime("%H%M", time.localtime(time.time())))
			if hourmin<910 and ("WinError" in str(e)): # 9点10分之前等待连接,之后连接不上报错
				print( f'委托数据服务等待连接...')
				time.sleep(15)
				continue
			# 关闭客户端
			client_socket.close()
			print(f"委托数据服务出错了({x+1})({e})")
			time.sleep(1)
			continue

# ========================================================================================
# 如有疑问+v信: 176516531 #
if __name__ == '__main__':

	
	# 成交数据进程
	p_get_trans = multiprocessing.Process(target=get_trans, name='GET_TRANS', args=(TRANS_CONF, ), daemon=True)
	p_get_trans.start()
	time.sleep(1)

	# 委托数据进程
	p_get_order = multiprocessing.Process(target=get_order, name='GET_ORDER', args=(ORDER_CONF, ), daemon=True)
	p_get_order.start()
	time.sleep(1)

	p_get_trans.join()
	p_get_order.join()

Python订阅版

# 订阅版客户端
import socket
import multiprocessing
import time
import struct
import os

# 配置地址端口用户口令
TRANS_CONF = {
	'HOST': 'x.x.x.x',
	'PORT': 9101,
	'TOKEN': 'test'
}

ORDER_CONF = {
	'HOST': 'x.x.x.x',
	'PORT': 9102,
	'TOKEN': 'test'
}

# 配置订阅证券代码
SUBSCR_CODE = '000001,600001'


# ========================================================================================
# 获取成交数据
def get_trans(my_conf):
	# 出错重连
	for x in range(3):
		try:
			# 定义参数
			my_host = my_conf['HOST']
			my_port = my_conf['PORT']
			my_token = my_conf['TOKEN']
			# 创建TCP套接字
			client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
			# 连接服务器
			client_socket.connect((my_host, my_port))
			# 设置连接参数
			client_socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024*1024)  # 发送缓存大小为1MB(默认64KB)
			client_socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 256*1024*1024)  # 接收缓存大小为256MB(默认64KB)
			client_socket.settimeout(15)
			# 发送【口令+订阅信息】进行登录,用逗号分割
			mylogin = my_token+','+SUBSCR_CODE
			client_socket.sendall(mylogin.encode("UTF-8"))
			print(f"登录成交数据服务器[{my_host}:{my_port}@{my_token}]")
			# 登录成功,会收到数据(盘中)或心跳(休市);
			# 登录失败,会收不到任何回应,并抛出超时。
			last_buffer = b'' # 存放未完整未处理的字节数据
			# 计算单笔数据大小
			format_size = struct.calcsize(">6s4IQ2B2I2s") # 网络传输数据采用大端模式,format_size = 42 bytes
			# 生成解包对象示例
			mystruct = struct.Struct(">6s4IQ2B2I2s")
			# 设置每次接收数据长度
			recv_len = int(format_size*100000)
			# =================================================================
			# 示例————输出到文件和屏幕打印笔数
			if not os.path.isfile("Sample_Trans.csv"):
				title = "本地时间, 证券代码, 成交时间, 成交编号, 成交单价, 成交数量, 成交金额, 交易方向, 交易类型, 买方委托编号, 卖方委托编号, 结束符号\n"
			else:
				title = ""
			file_object = open("Sample_Trans.csv", "a")
			file_object.write(title)
			file_object.flush() 
			# =================================================================
			# 循环接收数据
			while True:
				# 定义数据列表
				datalist = [] 
				# 接收字节数据
				buffer = client_socket.recv(recv_len)
				# 新旧数据合并
				buffer = last_buffer + buffer 
				# 计算完整笔数
				data_count = int(len(buffer)/format_size)
				# 网络传输字节序列有时并非整笔到达,需要计算最后整笔位置
				end = data_count*format_size
				# 保存未完一笔
				last_buffer = buffer[end:] 
				# 处理完整逐笔
				offset = 0
				for i in range(data_count):
					# 取一笔进行处理,每次向后移动
					data = mystruct.unpack_from(buffer, offset) # 网络传输数据采用大端模式,format_size = 42 bytes
					offset += format_size
					if data[0]==b'HEARTB': # 跳过心跳
						continue
					datalist.append(data) # 加入数据列表以供后续使用
				# print(data)
				# =================================================================
				# 用户定义如何使用数据
				# 示例————输出到文件和屏幕打印笔数
				now = time.strftime("%H:%M:%S", time.localtime(int(time.time())))
				for line in datalist:
					line = list(line)
					line[0] = line[0].decode()
					line[10] = line[10].decode()
					file_object.write(now+", "+str(line)+"\n")
				file_object.flush() 
				print(f"[{now}] 收到成交数据{len(datalist)}笔,写入文件Sample_Trans.csv")
				# =================================================================
				# time.sleep(1)
		except Exception as e:
			hourmin = int(time.strftime("%H%M", time.localtime(time.time())))
			if hourmin<910 and ("WinError" in str(e)): # 9点10分之前等待连接,之后连接不上报错
				print(f'成交数据服务等待连接...')
				time.sleep(15)
				continue
			# 关闭客户端
			client_socket.close()
			print(f"成交数据服务出错了({x+1})({e})")
			time.sleep(1)
			continue

# 获取委托数据
def get_order(my_conf):
	# 出错重连
	for x in range(3):
		try:
			# 定义参数
			my_host = my_conf['HOST']
			my_port = my_conf['PORT']
			my_token = my_conf['TOKEN']
			# 创建TCP套接字
			client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
			# 连接服务器
			client_socket.connect((my_host, my_port))
			# 设置连接参数
			client_socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024*1024)  # 发送缓存大小为1MB(默认64KB)
			client_socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 256*1024*1024)  # 接收缓存大小为256MB(默认64KB)
			client_socket.settimeout(15)
			# 发送【口令+订阅信息】进行登录,用逗号分割
			mylogin = my_token+','+SUBSCR_CODE
			client_socket.sendall(mylogin.encode("UTF-8"))
			print(f"登录委托数据服务器[{my_host}:{my_port}@{my_token}]")
			# 登录成功,会收到数据(盘中)或心跳(休市);
			# 登录失败,会收不到任何回应,并抛出超时。
			last_buffer = b'' # 存放未完整未处理的字节数据
			# 计算单笔数据大小
			format_size = struct.calcsize(">6s4I2B2s") # 网络传输数据采用大端模式,format_size = 26 bytes
			# 生成解包对象示例
			mystruct = struct.Struct(">6s4I2B2s")
			# 设置每次接收数据长度
			recv_len = int(format_size*100000)
			# =================================================================
			# 示例————输出到文件和屏幕打印笔数
			if not os.path.isfile("Sample_Order.csv"):
				title = "本地时间, 证券代码, 委托时间, 委托编号, 委托单价, 委托数量, 交易方向, 交易类型, 结束符号\n"
			else:
				title = ""
			file_object = open("Sample_Order.csv", "a")
			file_object.write(title)
			file_object.flush() 
			# =================================================================
			# 循环接收数据
			while True:
				# 定义数据列表
				datalist = [] 
				# 接收字节数据
				buffer = client_socket.recv(recv_len)
				# 新旧数据合并
				buffer = last_buffer + buffer 
				# 计算完整笔数
				data_count = int(len(buffer)/format_size)
				# 网络传输字节序列有时并非整笔到达,需要计算最后整笔位置
				end = data_count*format_size
				# 保存未完一笔
				last_buffer = buffer[end:] 
				# 处理完整逐笔
				offset = 0
				for i in range(data_count):
					# 取一笔进行处理,每次向后移动
					data = mystruct.unpack_from(buffer, offset) # 网络传输数据采用大端模式,format_size = 42 bytes
					offset += format_size
					if data[0]==b'HEARTB': # 跳过心跳
						continue
					datalist.append(data) # 加入数据列表以供后续使用
				# print(data)
				# =================================================================
				# 用户定义如何使用数据
				# 示例————输出到文件和屏幕打印笔数
				now = time.strftime("%H:%M:%S", time.localtime(int(time.time())))
				for line in datalist:
					line = list(line)
					line[0] = line[0].decode()
					line[7] = line[7].decode()
					file_object.write(now+", "+str(line)+"\n")
				file_object.flush() 
				print(f"[{now}] 收到委托数据{len(datalist)}笔,写入文件Sample_Order.csv")
				# =================================================================
				# time.sleep(1)
		except Exception as e:
			hourmin = int(time.strftime("%H%M", time.localtime(time.time())))
			if hourmin<910 and ("WinError" in str(e)): # 9点10分之前等待连接,之后连接不上报错
				print( f'委托数据服务等待连接...')
				time.sleep(15)
				continue
			# 关闭客户端
			client_socket.close()
			print(f"委托数据服务出错了({x+1})({e})")
			time.sleep(1)
			continue

# ========================================================================================
# 如有疑问+v信: 176516531 #
if __name__ == '__main__':

	
	# 成交数据进程
	p_get_trans = multiprocessing.Process(target=get_trans, name='GET_TRANS', args=(TRANS_CONF, ), daemon=True)
	p_get_trans.start()
	time.sleep(1)

	# 委托数据进程
	p_get_order = multiprocessing.Process(target=get_order, name='GET_ORDER', args=(ORDER_CONF, ), daemon=True)
	p_get_order.start()
	time.sleep(1)

	p_get_trans.join()
	p_get_order.join()



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值