《股票魔法师》趋势模板——聚宽实现

import pandas as pd
from jqdata import *
from datetime import datetime, timedelta
from jqlib.technical_analysis import *

today = datetime.now().date()
yesterday = today - timedelta(days=1)
TRADE_DATE = today

MA_SHORT = 150  # 短期均线周期
MA_LONG = 200  # 长期均线周期
LOOKBACK_DAYS = 365  # 获取历史数据的天数(需大于最大均线周期)


def filter_stocks():
    # ==================== 获取所有A股股票列表 ====================
    # 获取所有股票,排除ST、退市等
    stocks = get_all_securities(types=['stock'], date=TRADE_DATE)
    stock_list = stocks.index.tolist()
    name_map = stocks['display_name'].to_dict()

    # ==================== 获取历史行情数据 ====================
    # 计算需要回溯的起始日期(往前推LOOKBACK_DAYS个交易日)
    # 使用get_trade_days获取交易日列表,确保只取交易日
    trade_days = get_trade_days(end_date=TRADE_DATE, count=LOOKBACK_DAYS)
    start_date = trade_days[0]

    print(f"数据起始日期: {start_date}, 截止日期: {TRADE_DATE}")

    # 批量获取所有股票的历史收盘价
    # fields='close' 只获取收盘价,skip_paused=True跳过停牌日
    price_data = get_price(
        stock_list,
        start_date=start_date,
        end_date=TRADE_DATE,
        frequency='daily',
        fields=['high', 'low', 'close'],
        fill_paused=True,
        fq='pre'  # 前复权
    )

    # 提取收盘价数据(DataFrame格式:行=日期,列=股票代码)
    close_prices = price_data['close']
    high_prices = price_data['high']
    low_prices = price_data['low']

    # ==================== 计算均线并筛选 ====================
    # 计算MA50、MA150、MA200
    ma_50 = close_prices.rolling(window=50).mean().iloc[-1]
    ma_150 = close_prices.rolling(window=150).mean().iloc[-1]
    ma_200 = close_prices.rolling(window=200).mean().iloc[-1]
    ma_200_30d_ago = close_prices.rolling(window=200).mean().iloc[-30]

    # 计算一年最高价
    max_250 = high_prices.rolling(window=250).max().iloc[-1]

    # 计算一年最低价
    min_250 = low_prices.rolling(window=250).min().iloc[-1]

    # 计算差值并生成逐只股票的条件
    ma200_series = close_prices.rolling(window=200).mean()
    ma200_diff = ma200_series.diff()
    # 最近30个差值是否全部大于0(逐股票)
    ma200_up30_condition = (ma200_diff.iloc[-30:] > 0).all(axis=0)

    # 获取最新一天的收盘价、150日均线、200日均线
    latest_close = close_prices.iloc[-1]

    # 计算相对强度
    close_250_ago = close_prices.iloc[-250]  # 250个交易日前的收盘价(按位置索引)

    returns_250 = (close_prices.iloc[-1] / close_250_ago) - 1  # 涨跌幅

    # 计算相对强度(百分位排名,涨幅越小排名越靠前)
    # rank(ascending=False, pct=True) 返回0~1,乘以100得到0~100
    relative_strength = 100 * returns_250.rank(ascending=True, pct=True)

    condition = (
            (latest_close > ma_150) &  # 1. 当前股价在150日线和200日线上方
            (latest_close > ma_200) &  # 1. 当前股价在150日线和200日线上方
            (latest_close > ma_50) &  # 5. 当前股价高于50日线
            (ma_150 > ma_200) &  # 2. 150日线在200日线上方
            (ma_50 > ma_150) &  # 4. 50日线高于150日线和200日线
            (ma_50 > ma_200) &  # 4. 50日线高于150日线和200日线
            (latest_close > max_250 * 0.75) &  # 7. 当前价格至少处在最近一年最高价的75%以内
            (latest_close > min_250 * 0.3) &  # 6. 当前股价比最近一年最低股价至少高30%
            ma200_up30_condition &
            (relative_strength > 70) &  # 8. 相对强度大于70
            (ma_50.notna()) &
            (ma_150.notna()) &
            (ma_150.notna()) &
            (max_250.notna()) &
            (min_250.notna()) &
            (latest_close.notna())
    )

    selected_codes = latest_close[condition].index.tolist()
    selected_names = [name_map.get(code, code) for code in selected_codes]  # 若未找到则保留代码

    print(selected_names)


filter_stocks()
posted @ 2026-08-10 13:55  KiroshiX  阅读(27)  评论(0)    收藏  举报