先进先出匹配交易
2023-10-11 本文已影响0人
黄yy家的jby
class Item(object):
"""单笔交易对象,存储购买日期和数量 可能是买入也可能是卖出"""
def __init__(self, time, num):
if type(time) is int or type(time) is str:
self.time = datetime.datetime.strptime(str(time),'%Y%m%d')
else:
self.time = time
if type(num) is str:
self.num = int(num)
else:
self.num = num
class Position(object):
"""头寸对象,存储某人员对于某股票的全部头寸 以队列模式先进先出"""
def __init__(self, stock_name, person_name):
self.items = []
self.stock_name = stock_name
self.person_name = person_name
def is_empty(self):
return self.items == []
def buy(self, item):
"""有买入则在items列表里追加此次交易记录"""
self.items.append(item)
def sell(self, item, limit):
"""根据卖出的交易记录更新本头寸 返回可能存在的相关交易信息(以元组的列表返回)"""
related = []
# 首次记录先是卖的,则pass
if len(self.items) == 0 :
return related
else:
# 不断根据卖出数量抵消买入记录,时间最久远的先被抵消,完全抵消后离开队列,卖出数量抵完为止
while item.num > 0:
# 判断此次抵消的买入记录是否和卖出记录的日期差≤limit天
if (item.time.date() - self.items[0].time.date()).days <= limit:
# 发现相关交易,将相关信息打包为元组,放入列表related
info = (self.person_name, self.stock_name, self.items[0].time,
self.items[0].num,
item.time,
min(item.num,self.items[0].num),
(item.time.date() - self.items[0].time.date()).days)
related.append(info)
# 判断最远的一次买入是否能完全抵消剩余卖出数量(临界值稍微注意,和不能一样也需要删除队列头)
if item.num >= self.items[0].num:
# 不能,则先用最远的买入抵消部分卖出,剩余的卖出数量继续被后面的买入抵消
item.num -= self.items[0].num
# 最远的买入记录离开队列,循环继续
del (self.items[0])
if len(self.items) == 0: # 如果卖的比买的多,直接跳出循环
return related
else:
# 能,则最远的买入记录完全消化剩余卖出数量,并留有余量,下一次循环会停止
self.items[0].num -= item.num
item.num = 0
return related
def FIFO(df,col_people,col_stock,col_time,col_num,col_type,limit=1e4):
df = df.sort_values(by=col_time)
# dic 以人员,股票为索引存储所有头寸的字典
dic = {}
relate = []
for row in df.iterrows():
name = row[1][col_people]
date = row[1][col_time]
stock = row[1][col_stock]
num = row[1][col_num]
type = row[1][col_type]
index = name + ','+stock
if index not in dic:
dic[index] = Position(person_name=name, stock_name=stock)
if type == '买入':
dic[index].buy(Item(date, num))
else:
#卖出交易返回信息
relate += (dic[index].sell(Item(date,num),limit))
print(name,date,stock,type)
result = pd.DataFrame(relate)
result.columns = ['PERSON','INSTRUMENT_CODE','BUY_TIME','BUY_VOLUME_CUMSUM','SELL_TIME','SELL_VOLUME','INTERVAL_DAYS']
return result