Python 模拟交易函数:支持多种购买策略和交易日检查
def simulate_trade(self, trade_list, trade_dates, close_dict, max_num=None):
# 模拟交易过程,并获取每个交易日和持有日的资金列表和资产列表,返回这两个列表
position = {} # 持仓字典,格式为{股票1: 持仓数量,}
cash = 100000 # 初始资金,单位为元
cash_list = [cash] # 资金列表,记录每个交易日的资金情况
asset_list = [cash] # 资产列表,记录每个交易日和持有日的总资产情况
date_list = []
# 将trade_list转换成买入字典和卖出字典
buy_dict = {} # 买入字典,格式为{日期: [股票1, 股票2],}
sell_dict = {} # 卖出字典,格式为{日期: [股票1, 股票2],}
for buy_date, sell_date, codes in trade_list:
for code in codes:
buy_dict.setdefault(buy_date, []).append(code)
sell_dict.setdefault(sell_date, []).append(code)
date_list.append(buy_date)
date_list.append(sell_date)
date_list = sorted(list(set(date_list)))
# 遍历每个交易日和持有日,模拟交易过程
for date in trade_dates:
# 检查是否是交易日
if date in date_list:
# 检查是否有需要卖出的股票
for code in sell_dict.get(date, []):
# 获取当天该股票的收盘价作为卖出价
if code not in close_dict:
continue
sell_price = close_dict[code].loc[date]
# 检查是否可以交易
while np.isnan(sell_price):
date = pd.to_datetime(date) + pd.Timedelta(days=1)
date = date.strftime('%Y-%m-%d')
if date not in close_dict:
break
sell_price = close_dict[code].loc[date]
if np.isnan(sell_price):
continue
# 计算卖出所得的资金,并更新持仓和资金
if code in position:
sell_amount = position[code] * sell_price
else:
print('%s持仓中找不到%s:
%s' % (date, code, ', '.join(position.keys())))
continue
cash += sell_amount
position.pop(code)
# 检查是否有需要买入的股票
for code in buy_dict.get(date, []):
# 获取当天该股票的收盘价作为买入价
if code not in close_dict:
continue
buy_price = close_dict[code].loc[date]
# 检查是否可以交易
while np.isnan(buy_price):
date = pd.to_datetime(date) + pd.Timedelta(days=1)
date = date.strftime('%Y-%m-%d')
if date not in close_dict:
break
buy_price = close_dict[code].loc[date]
if np.isnan(buy_price):
continue
# 计算可以买入的数量,并更新持仓和资金
buy_amount = cash / len(buy_dict[date]) # 平均分配资金
buy_volume = int(buy_amount / buy_price / 100) * 100 # 向下取整到100的倍数
if max_num is not None: # 检查是否需要限制买入股票数量
buy_volume = min(buy_volume, int(cash / max_num / buy_price / 100) * 100)
if code in position:
max_volume = int(0.1 * cash / position[code] / buy_price / 100) * 100 # 检查是否需要限制股票的仓位
buy_volume = min(buy_volume, max_volume)
if buy_volume > 0: # 检查资金是否足够买入
cash -= buy_volume * buy_price
position[code] = position.get(code, 0) + buy_volume
if max_num is not None and len(position) > max_num: # 检查是否需要卖出股票
excess_codes = sorted(position, key=lambda x: position[x], reverse=True)[max_num:]
for code in excess_codes:
sell_price = close_dict[code].loc[date]
if np.isnan(sell_price) or code not in position:
continue
sell_volume = position[code]
sell_amount = sell_volume * sell_price
cash += sell_amount
position.pop(code)
# 计算当天的总资产
cash_list.append(cash)
total_asset = cash
for code, volume in position.items():
if code not in close_dict:
continue
if date in close_dict[code].index:
price = close_dict[code].loc[date]
else:
sub = close_dict[code].loc[:date]
if len(sub) == 0:
logger.info('can not find %s for %s in
%s' % (date, code, sub))
price = sub.iloc[-1]
total_asset += volume * price
# 将当天的总资产加入到资金列表和资产列表中
asset_list.append(total_asset)
return cash_list, asset_list
原文地址: https://www.cveoy.top/t/topic/nMJ0 著作权归作者所有。请勿转载和采集!