BigQuant使用文档

涨停取消卖单

由iquant创建,最终由qxiao 被浏览 52 用户

导语

如果当天涨停了,尾盘不想卖出,可以取消前日产生的卖单。具体方法是在回测模块的盘前处理函数中加入当天涨停的判断,如果是涨停就取消订单

具体步骤

第一步: 我们通过增加一个输入特征和数据抽取模块获取每日股票的收盘涨跌停状态price_limit_status和名称字段name,然后传入回测模块。

在初始化函数中读取传入的股票名称数据

    context.options_data = context.options['data'].read()
    context.price_limit_status = context.options_data[['date','instrument','price_limit_status']]
    context.name_df = context.options_data[['date','instrument','name']]

在K线处理函数中将判断股票是否涨停,并进行st的判断,卖出st的股票。

# 回测引擎:每日数据处理函数, 每天执行一次
def bigquant_run(context, data):
    # 按日期过滤得到今日的预测数据
    ranker_prediction = context.data[
        context.data.date == data.current_dt.strftime("%Y-%m-%d")
    ]
    today = data.current_dt.strftime('%Y-%m-%d')
    
    # 1. 资金分配
    # 平均持仓时间是hold_days, 每日都将买入股票, 每日预期使用 1/hold_days 的资金
    # 实际操作中, 会存在一定的买入误差, 所以在前hold_days天, 等量使用资金;之后, 尽量使用剩余资金(这里设置最多用等量的1.5倍)
    is_staging = (
        context.trading_day_index < context.options["hold_days"]
    )  # 是否在建仓期间(前 hold_days 天)
    cash_avg = context.portfolio.portfolio_value / context.options["hold_days"]
    cash_for_buy = min(context.portfolio.cash, (1 if is_staging else 1.5) * cash_avg)
    cash_for_sell = cash_avg - (context.portfolio.cash - cash_for_buy)
    positions = {
        e: p.amount * p.last_sale_price for e, p in context.portfolio.positions.items()
    }
    equities = {e: e for e, p in context.portfolio.positions.items()}
    
    
    # 记录持仓中st的股票
    st_stock_list = []
    name_df = context.name_df
    name_today = name_df[name_df.date==today]
    for instrument in equities:
        name_instrument = name_today[name_today.instrument==instrument]['name'].values[0]
        # 如果股票状态变为了st 则卖出
        if 'ST' in name_instrument or '退' in name_instrument:
            # 指定一个limit_price,此时会以开盘价成交,这是由于初始化函数中改写了下单价格
            context.order_target(context.symbol(instrument), 0, limit_price=1.0)
            st_stock_list.append(instrument)
            cash_for_sell -= positions[instrument]
    if st_stock_list!=[]:
        print(today,'持仓出现st股/退市股',st_stock_list,'进行卖出处理')

    # 2. 生成卖出订单:hold_days天之后才开始卖出;对持仓的股票, 按机器学习算法预测的排序末位淘汰
    if not is_staging and cash_for_sell > 0:
        
        instruments = list(
            reversed(
                list(
                    ranker_prediction.instrument[
                        ranker_prediction.instrument.apply(lambda x: x in equities)
                    ]
                )
            )
        )
        price_limit_status = context.price_limit_status
        status_today = price_limit_status[price_limit_status.date==today]
        for instrument in instruments:
            # 如果是st股票已经卖过了,就跳过
            if instrument in st_stock_list:
                continue
            # 如果涨停就跳过股票
            status_instrument = status_today[status_today.instrument==instrument]['price_limit_status'].values[0]
            if status_instrument>2:
                continue
            context.order_target(instrument, 0)
            cash_for_sell -= positions[instrument]
            if cash_for_sell <= 0:
                break

    # 3. 生成买入订单:按机器学习算法预测的排序, 买入前面的stock_count只股票
    buy_cash_weights = context.stock_weights
    buy_instruments = list(ranker_prediction.instrument[: len(buy_cash_weights)])
    max_cash_per_instrument = (
        context.portfolio.portfolio_value * context.max_cash_per_instrument
    )
    for i, instrument in enumerate(buy_instruments):
        cash = cash_for_buy * buy_cash_weights[i]
        if cash > max_cash_per_instrument - positions.get(instrument, 0):
            # 确保股票持仓量不会超过每次股票最大的占用资金量
            cash = max_cash_per_instrument - positions.get(instrument, 0)
        if cash > 0:
            context.order_value(instrument, cash)

最后我们在盘前处理函数中加入当天涨停的判断,如果是涨停就取消订单。

# 交易引擎:每个单位时间开盘前调用一次。
def bigquant_run(context, data):
    from datetime import timedelta
    # 盘前处理,订阅行情等
    df_price_limit_status=context.price_limit_status.set_index('date')
    today=data.current_dt.strftime('%Y-%m-%d')
    # 得到当前未完成订单
    orders = context.get_open_orders()
    for order in orders:
        # 循环,撤销订单
        ins=str(order.symbol)
        # 如果前一日涨停,取消订单
        if  df_price_limit_status[df_price_limit_status.instrument==ins].price_limit_status.loc[today]==3 and order.direction=='2':
            context.cancel_order(order)
            print(today,'尾盘涨停取消卖单',ins)      

策略源码

https://bigquant.com/codesharev3/417adb34-4d09-40d6-bf7a-625e5ada05f0

\

评论
  • 为什么我的盘前处理函数里边的context.get_open_orders()无法获取任何订单,得出结果全是空白
{link}