Skip to content
All library documents

Screening Equities by Amplitude, Float Size, and Recent Market Attention

Code Qlib

Summary

This Chinese-language post describes a short-term equity selection screen based on three conditions: prior-session price amplitude above a threshold, tradable share count at or below a stated limit, and appearance on the previous day’s exchange activity list. It frames the filters as a way to find volatile, relatively small-float stocks that have attracted market attention. The post also provides formula and Python examples, with the Python version ranking qualifying names by turnover rate and retaining a fraction of the candidate list.

The article gives no backtest, return series, or evidence that the screen has predictive value. It warns that attention data is backward-looking and delayed, that short-term filters can be noisy, and that relying on publicity may neglect company fundamentals and sector context. It suggests adding fundamental variables, other technical criteria, market-attention measures, or machine-learning analysis, but does not test those proposed extensions. The thresholds and ranking are therefore presented as a screening recipe, not a demonstrated source of durable returns.

Key ideas

  • The screen combines recent price amplitude, a maximum float-size condition, and prior-day exchange attention data.
  • The sample implementation ranks qualifying stocks by turnover rate and limits the final selection count.
  • The post characterizes the approach as short-term and acknowledges that noisy moves can dominate its signals.
  • Exchange attention data is lagged and does not establish that a stock will continue moving in the same direction.
  • Fundamental and sector information are suggested as additions, but their effects are not evaluated.

Tags

Full text
# gen_training_orders.py


```py
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

import os
import numpy as np
import pandas as pd

from pathlib import Path

DATA_PATH = Path(os.path.join("data", "pickle", "backtest"))
OUTPUT_PATH = Path(os.path.join("data", "orders"))


def generate_order(stock: str, start_idx: int, end_idx: int) -> bool:
    dataset = pd.read_pickle(DATA_PATH / f"{stock}.pkl")
    df = dataset.handler.fetch(level=None).reset_index()
    if len(df) == 0 or df.isnull().values.any() or min(df["$volume0"]) < 1e-5:
        return False

    df["date"] = df["datetime"].dt.date.astype("datetime64")
    df = df.set_index(["instrument", "datetime", "date"])
    df = df.groupby("date", group_keys=False).take(range(start_idx, end_idx)).droplevel(level=0)

    order_all = pd.DataFrame(df.groupby(level=(2, 0), group_keys=False).mean().dropna())
    order_all["amount"] = np.random.lognormal(-3.28, 1.14) * order_all["$volume0"]
    order_all = order_all[order_all["amount"] > 0.0]
    order_all["order_type"] = 0
    order_all = order_all.drop(columns=["$volume0"])

    order_train = order_all[order_all.index.get_level_values(0) <= pd.Timestamp("2021-06-30")]
    order_test = order_all[order_all.index.get_level_values(0) > pd.Timestamp("2021-06-30")]
    order_valid = order_test[order_test.index.get_level_values(0) <= pd.Timestamp("2021-09-30")]
    order_test = order_test[order_test.index.get_level_values(0) > pd.Timestamp("2021-09-30")]

    for order, tag in zip((order_train, order_valid, order_test, order_all), ("train", "valid", "test", "all")):
        path = OUTPUT_PATH / tag
        os.makedirs(path, exist_ok=True)
        if len(order) > 0:
            order.to_pickle(path / f"{stock}.pkl.target")
    return True


np.random.seed(1234)
file_list = sorted(os.listdir(DATA_PATH))
stocks = [f.replace(".pkl", "") for f in file_list]
np.random.shuffle(stocks)

cnt = 0
for stock in stocks:
    if generate_order(stock, 0, 240 // 5 - 1):
        cnt += 1
        if cnt == 100:
            break

```

Shown in full with attribution under the source's licence. Licence: MIT

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.