166-日频策略如何使用日内执行逻辑
由qxiao创建,最终由qxiao 被浏览 3 用户
当我们在用可视化模块构建日频策略的时候,如果想添加日内的执行逻辑,例如高开两个点买入,或者在日内指定时间买入,应该如何修改代码呢?\n实际上,我们只需要读取日频策略的调仓数据,然后调用这个数据接入日内回测即可,下面以平台内置的Stockranker可视化模板策略为例,讲解如何实现日内执行逻辑。
首先删除回测模块m7,通过读取m6.data,我们就已经得到了每日的预测数据。
此时就可以直接调用,当然你也可以把预测数据先在本地储存为csv格式,然后再进行调用,这样就不需要每次运行再加载一次预测数据。
pred_df = m6.data.read()
# 先储存为csv格式,再读取
# m6.data.read().to_csv('/home/aiuser/work/我的文档/pred_data.csv', index=False)/home/aiuser/work/我的文档
# pred_df = pd.read_csv('/home/aiuser/work/我的文档/pred_data.csv')
我们规定日内执行逻辑为:持仓10只,每5日调仓,在调仓的前一天14:55卖出不在前十的股票,在调仓日9:50买入在前十但未持有的股票。
然后把预测数据接入下面的日内执行代码,注意这里的持仓数量、调仓周期、回测时间都需要按实际调整。
import pandas as pd
import numpy as np
import bigtrader
from bigtrader.constant import OrderType, Direction
def initialize(context):
"""初始化函数"""
context.set_stock_t1(1)
from bigtrader.finance.commission import PerOrder
context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
# ========== 策略参数设置 ==========
context.stock_num = 10 # 持仓数量
context.holding_days = 5 # 调仓周期(持仓天数)
# ================================
# 加载预测数据
context.pred_df = pred_df
context.last_buy_date = None # 记录上次买入日期
context.days_since_buy = 0 # 距离上次买入的天数
print(f"策略初始化完成,预测数据共 {len(context.pred_df)} 行")
print(f"持仓数量: {context.stock_num}只 | 调仓周期: {context.holding_days}天")
def before_trading_start(context, data):
"""每日盘前处理"""
context.current_date = data.current_dt.strftime('%Y-%m-%d')
# 如果已经买入过,天数+1
if context.last_buy_date is not None:
context.days_since_buy += 1
# 获取前一个交易日的日期(用于读取信号)
prev_trading_day = context.add_trading_days(context.current_date, -1)
prev_date_str = prev_trading_day.strftime('%Y-%m-%d') if prev_trading_day else None
# 获取前一个交易日的信号(用于今天交易)
if prev_date_str:
historical_df = context.pred_df[context.pred_df['date'] <= prev_date_str]
if len(historical_df) > 0:
max_date = historical_df['date'].max()
today_signals = historical_df[historical_df['date'] == max_date]
context.daily_ins_pool = list(
today_signals.sort_values('score', ascending=False)
.head(context.stock_num)['instrument']
)
context.weight = 1.0 / len(context.daily_ins_pool) if len(context.daily_ins_pool) > 0 else 0
else:
context.daily_ins_pool = []
context.weight = 0
# 获取当前持仓
stock_hold_now = context.portfolio.positions
# 订阅
context.subscribe_bar(context.daily_ins_pool)
context.subscribe_bar(stock_hold_now.keys())
# 标记已交易的股票
context.trade_ins = []
def handle_data(context, data):
"""盘中交易逻辑"""
current_time = data.current_dt.strftime('%H:%M')
# 09:50 买入 - 只有在调仓日或首次买入时才执行
if current_time == "09:50":
# 首次买入 或者 距离上次买入满足调仓周期
if context.last_buy_date is None or context.days_since_buy >= context.holding_days:
print(f"[{context.current_date} 09:50] 调仓日买入 | 距上次:{context.days_since_buy}天 | 目标池:{len(context.daily_ins_pool)}只")
for ins in context.daily_ins_pool:
if ins not in context.trade_ins:
try:
context.order_target_percent(ins, context.weight)
context.trade_ins.append(ins)
except Exception as e:
print(f" 买入失败: {ins} | {e}")
# 更新上次买入日期
context.last_buy_date = context.current_date
context.days_since_buy = 0
# 14:55 卖出 - 只有在调仓日前一天才执行
elif current_time == "14:55":
# 距离上次买入第(holding_days-1)天(明天是调仓日)
if context.days_since_buy == context.holding_days - 1:
stock_hold_now = context.portfolio.positions
if len(stock_hold_now) > 0:
# 卖出不在明天目标池中的股票
stocks_to_sell = [ins for ins in stock_hold_now.keys()
if ins not in context.daily_ins_pool]
if len(stocks_to_sell) > 0:
print(f"[{context.current_date} 14:55] 调仓前一天卖出 | 持仓:{len(stock_hold_now)}只 | 卖出:{len(stocks_to_sell)}只")
for ins in stocks_to_sell:
try:
context.order_target_percent(ins, 0)
except Exception as e:
print(f" 卖出失败: {ins} | {e}")
def handle_order(context, order):
"""委托回报推送"""
pass
def handle_trade(context, trade):
"""成交回报推送"""
pass
# 运行回测
print("="*60)
print("开始分钟级回测...")
print("="*60)
performance = bigtrader.run(
market=bigtrader.Market.CN_STOCK,
frequency=bigtrader.Frequency.MINUTE,
start_date='2023-01-01',
end_date='2024-01-01',
capital_base=1000000,
initialize=initialize,
handle_data=handle_data,
handle_trade=handle_trade,
handle_order=handle_order,
before_trading_start=before_trading_start
)
performance.render()
当然,如果还要接入其他日内执行逻辑,可以借助大模型就在这个模板下进行修改。