模拟计数的问题
由bqetoybg创建,最终由bqetoybg 被浏览 7 用户
我在策略的handledata函数里有下面一段代码\n
# 记录新股票及其买入时的交易日索引
context.holdings.append((best_code, current_idx))
context.logger.info(f"持仓情况{context.holdings}, 计数{current_idx}")
context.bought_today = True
用来记录买入的标的和时间,回测时运行正常,但是提交模拟后发现,在确信有持仓的情况下,每天买入股票之前context.holdings都是空的,请问怎么回事,怎么处理?
还有一个问题:trade_dates = dai.query("""
SELECT date
FROM all_trading_days""",
filters={"date": ["2020-01-01", "2020-01-31"]}).df()
trade_dates.tail()查询结果如下的DataFrame
date
52 2020-01-29
53 2020-01-30
54 2020-01-30
55 2020-01-31
56 2020-01-31\n每个日期都出现两遍,并且最后这几个日期都不是交易日
\
def initialize(context: bigtrader.IContext):
"""
回测初始化:设置因子数据、持仓记录
"""
context.data = []
# 持仓列表,每个元素为 (instrument, 买入时的交易日索引)
context.holdings = []
# 记录今天是否已经执行过卖出(每天只能卖一次)
# context.sold_today = False
# 记录今天是否已经执行过买入(每天只能买一次)
context.bought_today = False
def before_trading(context: IContext, data: IBarData):
"""盘前重置每日交易标记"""
context.bought_today = False
def handle_data(context: bigtrader.IContext, data: bigtrader.IBarData):
current_date = data.current_dt.strftime("%Y-%m-%d")
current_idx = context.trading_day_index
sql = """
查询内容略
"""
e_date = context.current_dt
s_date = e_date - timedelta(100)
筛选过程略去
data = data.sort_values(['daily_return'], ascending=[False])
torch.manual_seed(99)
np.random.seed(99)
# ==================== 模型定义(二分类) ====================
class CNNClassifier(nn.Module):
def __init__(self, input_dim):
super(CNNClassifier, self).__init__()
self.conv1 = nn.Conv1d(in_channels=1, out_channels=64, kernel_size=1)
self.conv2 = nn.Conv1d(in_channels=64, out_channels=32, kernel_size=1)
self.global_pool = nn.AdaptiveAvgPool1d(1)
self.fc1 = nn.Linear(32, 64)
self.dropout = nn.Dropout(0.2)
self.fc2 = nn.Linear(64, 1) # 输出 logits
self.relu = nn.ReLU()
def forward(self, x):
x = self.relu(self.conv1(x))
x = self.relu(self.conv2(x))
x = self.global_pool(x)
x = x.view(x.size(0), -1)
x = self.relu(self.fc1(x))
x = self.dropout(x)
x = self.fc2(x)
return x
feature_cols = [col for col in data.columns if col not in ['date', 'instrument']]
model = CNNClassifier(input_dim=len(feature_cols))
model.load_state_dict(torch.load('/home/aiuser/work/codeplayground/cnn_classifier_2_5_target_5.pth'))
model.eval()
test_X = data[feature_cols].values.astype(np.float32) # 先取 values
test_X = torch.tensor(test_X, dtype=torch.float32).unsqueeze(1)
try:
with torch.no_grad():
y_pred_proba = torch.sigmoid(model(test_X)).cpu().numpy().flatten()
context.data = data[['date','instrument','daily_return','vol_ratio']]
context.data['pred_prob'] = y_pred_proba
context.data = context.data.dropna()
day_data = context.data.query('pred_prob>0.8').sort_values(['pred_prob','vol_ratio'], ascending=[False,False]).head(3)
except:
return
# 获取当日因子数据,按 pred_ret 降序排序
if day_data.empty:
return
# 当前持仓的股票代码
current_hold_codes = {h[0] for h in context.holdings}
context.logger.info(f"持仓情况{context.holdings}, 计数{current_idx}")
# ---------- 持有满3天就卖 ----------
if len(context.holdings) > 0:
for oldest_code, oldest_idx in context.holdings:
hold_days = current_idx - oldest_idx
if hold_days >= 3:
# 卖出到期股票
context.order_target_value(oldest_code, 0)
context.holdings.remove((oldest_code, oldest_idx))
# context.sold_today = True
# ---------- 买入逻辑:每天最多买一次,且确保买入后总持仓不超过3只 ----------
if not context.bought_today and len(context.holdings) < 3:
# 候选买入:当日得分最高且不在当前持仓中的股票
candidates = day_data[~day_data["instrument"].isin(current_hold_codes)]
if not candidates.empty:
best_code = candidates.iloc[0]["instrument"]
# 根据当前持仓数量决定买入金额比例
hold_count = len(context.holdings)
# 以下实现方式:获取当前账户信息,动态计算目标持仓比例。
total_value = context.get_available_cash() # 总资产
context.logger.info(f"可用资金{total_value}")
# 根据规则,本次买入应使用的现金比例
if hold_count == 0:
target_value = total_value / 3
elif hold_count == 1:
target_value = total_value / 2
elif hold_count == 2:
target_value = total_value
context.order_target_value(best_code, target_value)
# 记录新股票及其买入时的交易日索引
context.holdings.append((best_code, current_idx))
context.logger.info(f"持仓情况{context.holdings}, 计数{current_idx}")
context.bought_today = True
# 回测配置
performance = bigtrader.run(
market=bigtrader.Market.CN_STOCK,
frequency=bigtrader.Frequency.DAILY,
start_date='2026-01-01',
end_date='2026-06-30',
capital_base=100000, # 初始资金10万
initialize=initialize,
handle_data=handle_data,
before_trading_start=before_trading,
order_price_field_buy='open', # 以开盘价买入
order_price_field_sell='open' # 以开盘价卖出
)
我想实现的是持股三天就卖