这是一个股票交易委托数据表,需要对时间处于[93000000,145700000)的每笔委托单进行数据处理(93000000时间之前的数据已经处理完)。


# 盘中实时匹配计算
df_pz = df[(df['时间'] >= 93000000) & (df['时间'] < 145700000)] # 取集合竞价的数据
93000000(也就是集合竞价)之前的数据,里面有未成交的买单和卖单,每遍历到一个新的[93000000,145700000)之间的订单,就要在之前的未成交的订单里面进行查找相应的数据,并进行处理。
首先将93000000之前的订单进行分类:未成交买单,未成交卖单和已完成订单
# 集合竞价中的数据整理
df_jh = df[df['时间'] < 93000000]
# 集合竞价(93000000之前)未成交买单
df_b_wcj = df_jh[(df_jh['委托类型'] == 'A')&(df_jh['委托代码'] == 'B') & (df_jh['未成交数量'] > 0)]
# 集合竞价(93000000之前)未成交卖单
df_s_wcj = df_jh[(df_jh['委托类型'] == 'A')&(df_jh['委托代码'] == 'S') & (df_jh['未成交数量'] > 0)]
#交易已完成订单(完全撤单和已成交订单)+交易类型为D(撤单类型)的订单
df_ywc = df_jh[(df_jh['未成交数量'] == 0) | (df_jh['委托类型'] == 'D')]
然后开始对[93000000,145700000)的每笔委托单进行遍历数据处理。
for i, row in df_pz.iterrows():
遍历到的订单总共有4种类型:‘委托类型’为A,’委托代码‘为B的是委买订单,AS为委卖订单,DB为撤买订单,DS为撤卖订单。

如果遍历到的订单是委买订单(AB),那么需要查找:价格<=该订单’委托价格’的未成交的卖单(<=买价的卖单才能有资格成交)为符合条件的卖单,并且将符合条件的卖单按价格从低到高、交易所委托号从低到高进行排序,排在前面的优先成交。
# 如果遍历到的订单为AB买单
if (row['委托类型'] == 'A') & (row['委托代码'] == 'B'): # 遍历到的订单为买单
# 查找比该买单的委托价格低的未成交的卖单,为符合条件的卖单
df_s_wcj_match = df_s_wcj[df_s_wcj['委托价格'] <= row['委托价格']]
# 对符合条件的卖单进行按委托价格和交易所委托号全部升序排序
df_s_wcj_match_sorted = df_s_wcj_match.sort_values(by=['委托价格', '交易所委托号'], ascending=[True, True])
再判断查找到的符合匹配条件的卖单数量是否大于0:
如果等于0,说明前面未成交的卖单里面,没有价格<=AB单委托价格的卖单,即没有符合条件的卖单。这时就将AB单插入到未成交的买单集合里面。
if len(df_s_wcj_match) == 0: # 没有可成交的订单
row['未成交数量'] = row['委托数量'] # 未成交数量为委托数量
# 将该笔买单加入到未成交买单df里面
df_b_wcj = pd.concat([df_b_wcj, row.to_frame().T], ignore_index=True)
else: # 存在可成交的卖单
如果不等于0(只能是大于0),说明前面未成交的卖单里面,存在价格<=AB单委托价格的卖单,即存在符合条件的卖单。
else: # 存在可成交的卖单
num_wcj = 0
cumulative_sum_vol = 0
# 对可成交的卖单进行排序后遍历
for j, r in df_s_wcj_match_sorted.iterrows():
比如遍历到203行时,存在4个符合条件的卖单

对这4条卖单进行遍历,并判断累加卖单的未成交数量之和与买单委托数量之和哪个大
遍历第一条卖单:第一条及以前卖单的'未成交数量'之和<买单'委托数量'。
这时候就可以判定,遍历到的第一条卖单全部成交,买单数据部分成交
对遍历到的卖单进行处理:
设置它的成交数量为:原来的成交数量(这里数据有可能不为空)+','+这次的成交数量(即所有的未成交数量1300股全部成交)
设置它的成交时间为:原来的成交时间+','+这次的成交时间(及遍历到的买单的时间)
设置它的未成交数量为:0(这一步卖单全部成交)
将全部成交的卖单放入到已完成的订单集合里面
将全部成交的卖单,从未成交的卖单里面除掉(已经全部成交了)
对买单进行处理:
买单的成交数量就是:第一笔及之前卖单的'未成交数量'之和(cumulative_sum_vol)
买单的成交时间就是它自己的时间
买单的未成交数量是它自己的委托数量减去(第一笔及之前卖单的'未成交数量'之和--cumulative_sum_vol)
再将改买单放到未成交的买单集合里面
# 从遍历到的该笔卖单向前总的未成交卖单数量之和
cumulative_sum_vol += r['未成交数量']
# 如果遍历到的该笔卖单之前的总的未成交卖单数量之和小于买单的委托数量:
if cumulative_sum_vol < row['委托数量']: # 总的卖单未成交数量小于该行买单委托数量
# 卖单全部成交
r['成交数量'] = str(r['成交数量']) + ',' + str(r['未成交数量'])
r['成交时间'] = str(r['成交时间']) + ',' + str(row['时间'])
r['未成交数量'] = 0
# 将成交完成的卖单放入到已完成的订单集合里面
df_ywc = pd.concat([df_ywc, r.to_frame().T], ignore_index=True) # 把数据加入到已完成的订单里面
# 将卖单从未成交的卖单集合里面删除
df_s_wcj = df_s_wcj[df_s_wcj['交易所委托号'] != r['交易所委托号']] # 把数据从未成交的卖单里面删除
# 遍历到的买单部分成交
row['成交数量'] = str(cumulative_sum_vol)
row['成交时间'] = row['时间']
row['未成交数量'] = row['委托数量'] - cumulative_sum_vol
# 将未完全成交的买单放入未成交买单的集合中
df_b_wcj = pd.concat([df_b_wcj, row.to_frame().T], ignore_index=True)
处理完的第一条数据

继续遍历第二条符合条件的卖单:发现第二条及前面卖单(即第1、2条卖单)的'未成交数量'之和>买单'委托数量'
这时候就可以判定:遍历到的第二条卖单部分成交,买单全部成交
对第二条卖单的处理应该是:
第二笔卖单的'成交数量'为:买单的'委托数量'-(第一单卖单的成交数量),即:第二笔卖单的未成交数量-(两单未成交数量之和-买单委托数量),再加上第二笔卖单原有的'成交数量'。bug就出现在这里!无法赋值成功

第二笔卖单的成交时间为:之前的成交时间(可能有多次成交存在)+买单出现的'时间'
第二笔卖单的'未成交数量'为:两笔卖单‘未成交数量’之和减去买单的‘委托数量’
对买单的处理:
买单的'成交数量'=买单的委托数量(买单全部成交)
买单的'成交时间'=买单的'时间'
买单的'未成交数量' = 0
将该买单放入到已完成的订单集合里面
将该买单从未成交的买单集合里面删除
elif cumulative_sum_vol > row['委托数量']: # 总的卖单未成交数量大于该行买单委托数量
if num_wcj == 0: # 第一次遍历到大于0
# 未成交卖单部分成交
r['成交数量'] = str(r['成交数量']) + ',' + str(r['未成交数量'] - (cumulative_sum_vol - row['委托数量']))
r['成交时间'] = str(r['成交时间']) + ',' + str(row['时间'])
r['未成交数量'] = cumulative_sum_vol - row['委托数量']
# 遍历到的买单全部成交
row['成交数量'] = str(row['委托数量'])
row['成交时间'] = row['时间']
row['未成交数量'] = 0
df_b_wcj = df_b_wcj[df_b_wcj['交易所委托号'] != row['交易所委托号']] # 把row数据从未成交的卖单里面删除
df_ywc = pd.concat([df_ywc, row.to_frame().T], ignore_index=True) # 把数据加入到已完成的订单里面
num_wcj += 1
遍历到第三、四条的时候,因为买单已完成,所以不做任何处理
DB和DS委托单需要找到与之相同'交易所委托号'AB/AS订单,用AB/AS的'未成交数量'减去DB/DS的'委托数量':如果差值为0,就表示全部撤单,那么相对应的AB/AS订单'未成交数量'改为0,并放到已完成的订单合集里面,也将DB/DS订单放到已完成的订单里面,方便后面进行输出;如果差值大于0,就表示部分撤单,将AB/AS的'未成交数量'改为原'未成交数量'与DB/DS的'委托数量'的差值,也将DB/DS订单放到已完成的订单里面,方便后面进行输出。
在下面的代码里,第40行的值可以更改成功,第72行的值却更改不成功
文件在网盘[](链接:https://pan.baidu.com/s/1utmUzENRe_N0cGqseo9j-A?pwd=wipw
提取码:wipw
import pandas as pd
import time
pd.set_option('display.max_columns', None) # 显示所有列
pd.set_option('mode.chained_assignment', None)
df = pd.read_excel(r'E:\BaiduSyncdisk\quant\短线研究\盘口\603767\0616\集合竞价成交未成交处理.xlsx')
df['成交数量'] = df['成交数量'].astype(str) # 成交数量列改成字符串格式(一笔委托单可能分多次成交,需要插入多次)
# 盘中实时匹配计算
df_pz = df[(df['时间'] >= 93000000) & (df['时间'] < 145700000)] # 取集合竞价的数据
# 集合竞价中的数据整理
df_jh = df[df['时间'] < 93000000]
# 集合竞价(93000000之前)未成交买单
df_b_wcj = df_jh[(df_jh['委托类型'] == 'A') & (df_jh['委托代码'] == 'B') & (df_jh['未成交数量'] > 0)]
# 集合竞价(93000000之前)未成交卖单
df_s_wcj = df_jh[(df_jh['委托类型'] == 'A') & (df_jh['委托代码'] == 'S') & (df_jh['未成交数量'] > 0)]
# 交易已完成订单(撤单完成和已成交订单)+交易类型为D(撤单类型)的订单
df_ywc = df_jh[(df_jh['未成交数量'] == 0) | (df_jh['委托类型'] == 'D')]
# 对93000000-145700000之间的数据进行遍历处理
for i, row in df_pz.iterrows():
# 如果遍历到的订单为AB买单
if (row['委托类型'] == 'A') & (row['委托代码'] == 'B'): # 遍历到的订单为买单
# 查找比该买单的委托价格低的未成交的卖单,为符合条件的卖单
df_s_wcj_match = df_s_wcj[df_s_wcj['委托价格'] <= row['委托价格']]
# 对符合条件的卖单进行按委托价格和交易所委托号全部升序排序
df_s_wcj_match_sorted = df_s_wcj_match.sort_values(by=['委托价格', '交易所委托号'], ascending=[True, True])
if len(df_s_wcj_match) == 0: # 没有可成交的订单
row['未成交数量'] = row['委托数量'] # 未成交数量为委托数量
# 将该笔买单加入到未成交买单df里面
df_b_wcj = pd.concat([df_b_wcj, row.to_frame().T], ignore_index=True)
else: # 存在可成交的卖单
num_wcj = 0
cumulative_sum_vol = 0
# 对可成交的卖单进行排序后遍历
for j, r in df_s_wcj_match_sorted.iterrows():
# 从遍历到的该笔卖单向前总的未成交卖单数量之和
cumulative_sum_vol += r['未成交数量']
# 如果遍历到的该笔卖单之前的总的未成交卖单数量之和小于买单的委托数量:
if cumulative_sum_vol < row['委托数量']: # 总的卖单未成交数量小于该行买单委托数量
# 卖单全部成交
r['成交数量'] = str(r['成交数量']) + ',' + str(r['未成交数量'])
# r['成交数量']='00000'
r['成交时间'] = str(r['成交时间']) + ',' + str(row['时间'])
r['未成交数量'] = 0
# 将成交完成的卖单放入到已完成的订单集合里面
df_ywc = pd.concat([df_ywc, r.to_frame().T], ignore_index=True) # 把数据加入到已完成的订单里面
# 将卖单从未成交的卖单集合里面删除
df_s_wcj = df_s_wcj[df_s_wcj['交易所委托号'] != r['交易所委托号']] # 把数据从未成交的卖单里面删除
# 遍历到的买单部分成交
row['成交数量'] = str(cumulative_sum_vol)
row['成交时间'] = row['时间']
row['未成交数量'] = row['委托数量'] - cumulative_sum_vol
# 将未完全成交的买单放入未成交买单的集合中
df_b_wcj = pd.concat([df_b_wcj, row.to_frame().T], ignore_index=True)
elif cumulative_sum_vol == row['委托数量']: # 总的卖单未成交数量等于该行买单委托数量
# 卖单全部成交
r['成交数量'] = str(r['成交数量']) + ',' + str(r['未成交数量'])
r['成交时间'] = str(r['成交时间']) + ',' + str(row['时间'])
r['未成交数量'] = 0
# 将成交完成的卖单放入到已完成的订单集合里面
df_ywc = pd.concat([df_ywc, r.to_frame().T], ignore_index=True)
# 将卖单从未成交的卖单集合里面删除
df_s_wcj = df_s_wcj[df_s_wcj['交易所委托号'] != r['交易所委托号']]
# 遍历到的买单全部成交
row['成交数量'] = str(cumulative_sum_vol)
row['成交时间'] = row['时间']
row['未成交数量'] = 0
# 将成交完成的买单放入到已完成的订单集合里面
df_ywc = pd.concat([df_ywc, row.to_frame().T], ignore_index=True) # 把数据加入到已完成的订单里面
elif cumulative_sum_vol > row['委托数量']: # 总的卖单未成交数量大于该行买单委托数量
if num_wcj == 0: # 第一次遍历到大于0
# 未成交卖单部分成交
r['成交数量'] = str(r['成交数量']) + ',' + str(r['未成交数量'] - (cumulative_sum_vol - row['委托数量']))
r['成交时间'] = str(r['成交时间']) + ',' + str(row['时间'])
r['未成交数量'] = cumulative_sum_vol - row['委托数量']
# 遍历到的买单全部成交
row['成交数量'] = str(row['委托数量'])
row['成交时间'] = row['时间']
row['未成交数量'] = 0
df_b_wcj = df_b_wcj[df_b_wcj['交易所委托号'] != row['交易所委托号']] # 把row数据从未成交的卖单里面删除
df_ywc = pd.concat([df_ywc, row.to_frame().T], ignore_index=True) # 把数据加入到已完成的订单里面
num_wcj += 1
elif (row['委托类型'] == 'A') & (row['委托代码'] == 'S'): # 遍历到的订单为卖单
# 查找比该卖单的委托价格高的未成交的买单
df_b_wcj_match = df_b_wcj[df_b_wcj['委托价格'] >= row['委托价格']]
df_b_wcj_match_sorted = df_b_wcj_match.sort_values(by=['委托价格', '交易所委托号'], ascending=[False, True])
if len(df_b_wcj_match) == 0: # 没有可成交的买单
row['未成交数量'] = row['委托数量'] # 未成交数量为委托数量
# 将该笔卖单加入到未成交卖单df_s_wcj里面
df_s_wcj = pd.concat([df_s_wcj, row.to_frame().T], ignore_index=True)
else: # 存在可成交的买单
num_wcj = 0
cumulative_sum_vol = 0
for j, r in df_b_wcj_match_sorted.iterrows():
# 从该笔订单向前总的未成交数量之和
cumulative_sum_vol += r['未成交数量']
# print(cumulative_sum_vol)
if cumulative_sum_vol < row['委托数量']: # 总的卖单未成交数量小于等于该行买单委托数量
# 买单全部成交
r['成交数量'] = str(r['成交数量']) + ',' + str(r['未成交数量'])
r['成交时间'] = str(r['成交时间']) + ',' + str(row['时间'])
r['未成交数量'] = 0
# 将成交完成的买单放入到已完成的订单集合里面
df_ywc = pd.concat([df_ywc, r.to_frame().T], ignore_index=True) # 把数据加入到已完成的订单里面
# 将买单从未成交的买单集合里面删除
df_b_wcj = df_b_wcj[df_b_wcj['交易所委托号'] != r['交易所委托号']] # 把数据从未成交的卖单里面删除
# 遍历到的卖单部分成交
row['成交数量'] = str(cumulative_sum_vol)
row['成交时间'] = row['时间']
row['未成交数量'] = row['委托数量'] - cumulative_sum_vol
# 将未完全成交的卖单放入未成交买单的集合中
df_s_wcj = pd.concat([df_s_wcj, row.to_frame().T], ignore_index=True)
elif cumulative_sum_vol == row['委托数量']:
# 买单全部成交
r['成交数量'] = str(r['成交数量']) + ',' + str(r['未成交数量'])
r['成交时间'] = str(r['成交时间']) + ',' + str(row['时间'])
r['未成交数量'] = 0
# 将成交完成的买单放入到已完成的订单集合里面
df_ywc = pd.concat([df_ywc, r.to_frame().T], ignore_index=True)
# 将买单从未成交的买单集合里面删除
df_b_wcj = df_b_wcj[df_b_wcj['交易所委托号'] != r['交易所委托号']]
# 遍历到的卖单全部成交
row['成交数量'] = str(cumulative_sum_vol)
row['成交时间'] = row['时间']
row['未成交数量'] = 0
# 将成交完成的买单放入到已完成的订单集合里面
df_ywc = pd.concat([df_ywc, row.to_frame().T], ignore_index=True) # 把数据加入到已完成的订单里面
elif cumulative_sum_vol > row['委托数量']: # 总的卖单未成交数量大于该行买单委托数量
if num_wcj == 0: # 第一次遍历到大于0
# 未成交买单部分成交
r['成交数量'] = str(r['成交数量']) + ',' + str(
r['未成交数量'] - (cumulative_sum_vol - row['委托数量']))
r['成交时间'] = str(r['成交时间']) + ',' + str(row['时间'])
r['未成交数量'] = cumulative_sum_vol - row['委托数量']
# 遍历到的卖单全部成交
row['成交数量'] = str(row['委托数量'])
row['成交时间'] = row['时间']
row['未成交数量'] = 0
df_s_wcj = df_s_wcj[df_s_wcj['交易所委托号'] != row['交易所委托号']] # 把row数据从未成交的卖单里面删除
df_ywc = pd.concat([df_ywc, row.to_frame().T], ignore_index=True) # 把数据加入到已完成的订单里面
num_wcj += 1
# 遍历到的订单未DB撤买
elif (row['委托类型'] == 'D') & (row['委托代码'] == 'B'):
wt_num = row['交易所委托号'] # 提取撤单数据的交易所委托号
wt_num_a_data = df_b_wcj[df_b_wcj['交易所委托号'] == wt_num] # 找到交易所委托号相同的委托类型为AB的数据
diff_vol_ad = wt_num_a_data['委托数量'].values[0] - row['委托数量'] # 计算委托数量与撤单数量的差值
if diff_vol_ad > 0: # 如果差值大于0,未完全撤单
print(f'AB委托数量与DB委托数量之差大于0,已完成订单+1,其他不变')
wt_num_a_data['委托数量'] = diff_vol_ad
wt_num_a_data['未成交数量'] = diff_vol_ad # 将差值赋值给委托类型为A,交易所委托号相同数据的委托数量
wt_num_a_data['撤单数量'] = row['委托数量'] #
df_ywc = pd.concat([df_ywc, row.to_frame().T], ignore_index=True) # 将委托类型为D的订单,放到已完成的订单里面
elif diff_vol_ad == 0:
wt_num_a_data['未成交数量'] = 0
wt_num_a_data['撤单数量'] = row['委托数量'] #
df_ywc = pd.concat([df_ywc, row.to_frame().T], ignore_index=True) # 将撤单数据放到已完成订单里面
df_b_wcj = df_b_wcj[df_b_wcj['交易所委托号'] != wt_num] # 如果差值等于0,则将wt_num相等的数据从未成交的数据里面删除,放到已完成的数据里面,如下
df_ywc = pd.concat([df_ywc, wt_num_a_data], ignore_index=True) # 如果差值等于0,则将该条委托类型为A的数据追加到df_ywc中
elif (row['委托类型'] == 'D') & (row['委托代码'] == 'S'):
wt_num_a_data = df_s_wcj[df_s_wcj['交易所委托号'] == row['交易所委托号']] # 找到交易所委托号相同的委托类型为AS的数据
diff_vol_ad = wt_num_a_data['委托数量'].values[0] - row['委托数量'] # 计算委托数量与撤单数量的差值
# print(diff_vol_ad)
if diff_vol_ad > 0: # 如果差值大于0
wt_num_a_data['委托数量'] = diff_vol_ad
wt_num_a_data['未成交数量'] = diff_vol_ad # 将差值赋值给委托类型为A,交易所委托号相同数据的委托数量
wt_num_a_data['撤单数量'] = row['委托数量'] #
df_ywc = pd.concat([df_ywc, row.to_frame().T], ignore_index=True)
elif diff_vol_ad == 0:
wt_num_a_data['未成交数量'] = 0
wt_num_a_data['撤单数量'] = row['委托数量'] #
df_ywc = pd.concat([df_ywc, row.to_frame().T], ignore_index=True)
df_s_wcj = df_s_wcj[
df_s_wcj['交易所委托号'] != row['交易所委托号']] # 如果差值等于0,则将wt_num相等的数据从未成交的数据里面删除,放到已完成的数据里面,如下
df_ywc = pd.concat([df_ywc, wt_num_a_data], ignore_index=True) # 如果差值等于0,则将该条委托类型为A的数据追加到df_ywc中
if i == 203:
break
# 合并未成交买单、未成交卖单及已完成订单
merged_df = pd.concat([df_s_wcj, df_b_wcj, df_ywc])
merged_df = merged_df.sort_values(by=['时间', '交易所委托号'], ascending=[True, True])
merged_df = merged_df.reset_index(drop=True)
merged_df.to_excel(r'E:\BaiduSyncdisk\quant\短线研究\盘口\603767\0616\盘中实时成交未成交处理2.xlsx', index=False)