如何用Python编写均线金叉选股策略?

如何用Python编写均线金叉选股策略?缩略图

如何用Python编写均线金叉选股策略?

在量化投资中,技术分析是一种常用的方法,而均线(Moving Average)作为技术分析中最基础、最实用的指标之一,被广泛应用于趋势判断和交易信号生成。其中,均线金叉(Golden Cross)是一种经典的技术信号,通常预示着上涨趋势的开始。本文将详细介绍如何使用 Python 编写一个基于均线金叉的选股策略。


一、什么是均线金叉?

均线金叉是指短期均线从下方向上穿越长期均线,形成一个“金叉”形态。这通常被视为买入信号,意味着价格可能进入上涨趋势。例如,5日均线(MA5)上穿20日均线(MA20),即为一个常见的金叉信号。

相反,均线死叉(Death Cross)是指短期均线下穿长期均线,通常预示着下跌趋势的到来。


二、策略思路

本文将构建一个基于金叉的选股策略,核心逻辑如下:

  1. 数据获取:从指定数据源获取股票的历史价格数据。
  2. 计算均线:计算每只股票的短期和长期均线。
  3. 识别金叉信号:判断最近一个交易日是否出现金叉。
  4. 筛选股票池:选出所有出现金叉信号的股票。
  5. 输出结果:将符合条件的股票列表输出,供进一步分析或交易使用。

三、所需工具和库

本策略将使用以下 Python 库:

  • pandas:用于数据处理和分析。
  • numpy:用于数值计算。
  • tushareakshare:用于获取股票历史数据(本文以 akshare 为例)。
  • matplotlib(可选):用于可视化均线走势。

安装命令如下:

pip install pandas numpy akshare matplotlib

四、策略实现步骤

1. 获取股票数据

我们可以使用 akshare 来获取 A 股市场的股票列表和历史行情数据。

import akshare as ak
import pandas as pd

# 获取A股所有股票代码和名称
stock_list = ak.stock_info_a_code_name()
print(stock_list.head())

接下来,定义一个函数来获取某只股票的历史收盘价数据:

def get_stock_data(stock_code, start_date=\"20230101\", end_date=\"20241231\"):
    try:
        df = ak.stock_zh_a_hist(symbol=stock_code, period=\"daily\", start_date=start_date, end_date=end_date)
        df.rename(columns={\"日期\": \"date\", \"收盘\": \"close\"}, inplace=True)
        df[\"date\"] = pd.to_datetime(df[\"date\"])
        df.set_index(\"date\", inplace=True)
        return df[[\"date\", \"close\"]]
    except Exception as e:
        print(f\"获取 {stock_code} 数据失败: {e}\")
        return None

2. 计算均线并识别金叉信号

我们以 MA5 和 MA20 为例:

def detect_golden_cross(df, short_window=5, long_window=20):
    df[\"ma_short\"] = df[\"close\"].rolling(window=short_window).mean()
    df[\"ma_long\"] = df[\"close\"].rolling(window=long_window).mean()

    # 判断金叉
    df[\"golden_cross\"] = (df[\"ma_short\"] > df[\"ma_long\"]) & (df[\"ma_short\"].shift(1) <= df[\"ma_long\"].shift(1))

    return df

3. 遍历股票池,筛选出今日出现金叉的股票

def screen_golden_cross_stocks(stock_list, start_date=\"20230101\", end_date=\"20241231\"):
    golden_cross_stocks = []

    for index, row in stock_list.iterrows():
        stock_code = row[\"code\"]
        stock_name = row[\"name\"]
        df = get_stock_data(stock_code, start_date, end_date)

        if df is not None and len(df) > 20:
            df = detect_golden_cross(df)
            if df.iloc[-1][\"golden_cross\"]:
                golden_cross_stocks.append((stock_code, stock_name))
                print(f\"{stock_code} - {stock_name} 出现金叉\")

    return golden_cross_stocks

4. 运行策略并输出结果

if __name__ == \"__main__\":
    golden_cross_stocks = screen_golden_cross_stocks(stock_list)
    print(\"\\n今日出现金叉的股票:\")
    for code, name in golden_cross_stocks:
        print(f\"{code} - {name}\")

五、优化与扩展

上述策略是一个基础版本,实际应用中可以进一步优化和扩展:

1. 增加成交量筛选

在金叉出现时,若成交量放大,信号更可靠。可以加入成交量变化作为筛选条件。

2. 多均线组合

除了 MA5 与 MA20,也可以使用 MA10 与 MA30、MA20 与 MA60 等组合,观察不同周期的信号强度。

3. 回测系统

可以使用 backtraderzipline 等回测框架对策略进行历史回测,评估策略表现。

4. 实时监控

结合定时任务或事件驱动机制,实现每日收盘后自动筛选金叉股票,并推送提醒。

5. 结合其他指标

如 MACD、RSI、布林带等指标,构建多因子策略,提高信号的准确率。


六、可视化分析(可选)

可以使用 matplotlib 绘制某只股票的均线走势及金叉位置:

import matplotlib.pyplot as plt

def plot_golden_cross(df, stock_name):
    plt.figure(figsize=(12, 6))
    plt.plot(df[\"close\"], label=\"Close Price\", color=\"blue\")
    plt.plot(df[\"ma_short\"], label=\"MA5\", color=\"red\")
    plt.plot(df[\"ma_long\"], label=\"MA20\", color=\"green\")

    golden_cross_dates = df[df[\"golden_cross\"]][\"date\"]
    for date in golden_cross_dates:
        plt.axvline(x=date, color=\'orange\', linestyle=\'--\', alpha=0.5)

    plt.title(f\"{stock_name} 均线金叉图\")
    plt.legend()
    plt.show()

七、总结

均线金叉是一种简单但有效的技术分析信号,适用于趋势判断和择时操作。通过 Python 编写金叉选股策略,可以自动化地筛选出潜在上涨动能较强的股票,提高投资效率。

当然,任何单一技术指标都有其局限性。在实际应用中,建议结合基本面分析、市场情绪、资金流向等多维度信息,构建更稳健的投资策略。


八、附录:完整代码汇总

import akshare as ak
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 获取股票列表
stock_list = ak.stock_info_a_code_name()

# 获取股票历史数据
def get_stock_data(stock_code, start_date=\"20230101\", end_date=\"20241231\"):
    try:
        df = ak.stock_zh_a_hist(symbol=stock_code, period=\"daily\", start_date=start_date, end_date=end_date)
        df.rename(columns={\"日期\": \"date\", \"收盘\": \"close\"}, inplace=True)
        df[\"date\"] = pd.to_datetime(df[\"date\"])
        df.set_index(\"date\", inplace=True)
        return df[[\"date\", \"close\"]]
    except Exception as e:
        print(f\"获取 {stock_code} 数据失败: {e}\")
        return None

# 检测金叉信号
def detect_golden_cross(df, short_window=5, long_window=20):
    df[\"ma_short\"] = df[\"close\"].rolling(window=short_window).mean()
    df[\"ma_long\"] = df[\"close\"].rolling(window=long_window).mean()
    df[\"golden_cross\"] = (df[\"ma_short\"] > df[\"ma_long\"]) & (df[\"ma_short\"].shift(1) <= df[\"ma_long\"].shift(1))
    return df

# 绘图函数
def plot_golden_cross(df, stock_name):
    plt.figure(figsize=(12, 6))
    plt.plot(df[\"close\"], label=\"Close Price\", color=\"blue\")
    plt.plot(df[\"ma_short\"], label=\"MA5\", color=\"red\")
    plt.plot(df[\"ma_long\"], label=\"MA20\", color=\"green\")
    golden_cross_dates = df[df[\"golden_cross\"]][\"date\"]
    for date in golden_cross_dates:
        plt.axvline(x=date, color=\'orange\', linestyle=\'--\', alpha=0.5)
    plt.title(f\"{stock_name} 均线金叉图\")
    plt.legend()
    plt.show()

# 筛选金叉股票
def screen_golden_cross_stocks(stock_list, start_date=\"20230101\", end_date=\"20241231\"):
    golden_cross_stocks = []
    for index, row in stock_list.iterrows():
        stock_code = row[\"code\"]
        stock_name = row[\"name\"]
        df = get_stock_data(stock_code, start_date, end_date)
        if df is not None and len(df) > 20:
            df = detect_golden_cross(df)
            if df.iloc[-1][\"golden_cross\"]:
                golden_cross_stocks.append((stock_code, stock_name))
                print(f\"{stock_code} - {stock_name} 出现金叉\")
                plot_golden_cross(df, stock_name)  # 可选绘图
    return golden_cross_stocks

if __name__ == \"__main__\":
    golden_cross_stocks = screen_golden_cross_stocks(stock_list)
    print(\"\\n今日出现金叉的股票:\")
    for code, name in golden_cross_stocks:
        print(f\"{code} - {name}\")

如需进一步开发量化交易系统、构建多因子模型或接入交易接口,欢迎继续深入学习 Python 量化相关知识。

滚动至顶部