比赛讨论

因子分享-日内主动买入强度占比因子

由bqtnziby创建,最终由bqtnziby 被浏览 5 用户

1.主动买入定义及因子逻辑

主动买入金额:当分钟内收盘价 > 开盘价时,认为该分钟的成交由主动买入主导,此时主动买入金额等于该分钟的成交额;否则为 0。

相应的,被动买入金额即为 当分钟内收盘价 < 开盘价

当分钟内收盘价 > 开盘价时,认为买方更主动(愿意以更高价格买入),这类成交被归类为 “主动买入”。主动买入占比越高,说明当日买方主动进攻的力量越强。

主动买入占比:

(1)计算当日主动买入总金额

(2)计算当日总买入金额

(3)主动买入占比=主动买入总金额/总买入金额

2.次日相对涨跌幅

次日相对涨跌幅 =(次日收盘价 - 当日收盘价)/ 当日收盘价

3.最终因子

最终因子=主动买入占比*次日相对涨跌幅

因子通过乘以 “次日相对涨跌幅”,将主动买入力量与短期收益关联。逻辑是:若主动买入力量强(占比高)且次日确实上涨(涨跌幅为正),则因子值高,代表 “主动买入力量有效转化为后续收益”;反之,若主动买入力量强但次日下跌,因子值会较低甚至为负。

4.核心部分代码

    sql = f"""
        WITH minute_active_passive AS (
            SELECT
                trading_day,
                instrument,
                date,
                amount,
                close,
                open,
                CASE WHEN close > open THEN amount ELSE 0 END AS active_buy_amount,
                CASE WHEN close < open THEN amount ELSE 0 END AS passive_buy_amount
            FROM {datasource}
            WHERE close > 0 AND amount > 0
        ),
        daily_agg AS (
            SELECT
                trading_day,
                instrument,
                SUM(active_buy_amount) AS sum_active,
                SUM(active_buy_amount + passive_buy_amount) AS sum_total,
                MAX(date) AS last_dt
            FROM minute_active_passive
            GROUP BY trading_day, instrument
            HAVING SUM(active_buy_amount + passive_buy_amount) > 0
        ),
        daily_active_ratio AS (
            SELECT
                a.trading_day,
                a.instrument,
                CAST(a.sum_active AS DOUBLE) / NULLIF(a.sum_total, 0) AS active_buy_ratio,
                mc.close AS day_close
            FROM daily_agg a
            LEFT JOIN minute_active_passive mc
                ON mc.trading_day = a.trading_day AND mc.instrument = a.instrument AND mc.date = a.last_dt
        ),
        factor_result AS (
            SELECT
                STRPTIME(CAST(trading_day AS VARCHAR), '%Y%m%d') AS date,
                instrument,
                active_buy_ratio * ((LEAD(day_close) OVER (PARTITION BY instrument ORDER BY trading_day) - day_close) / NULLIF(day_close, 0)) AS factor
            FROM daily_active_ratio
        )
        SELECT date, instrument, factor FROM factor_result WHERE factor IS NOT NULL
    """

    lookback_days = 3
    query_start_date = pd.to_datetime(start_date) - pd.Timedelta(days=lookback_days)
    df = dai.query(sql, filters={'date': [query_start_date, end_date]}, compression=True).df()
    df = df[df['date'].between(start_date, end_date)]

    return df

\

{link}