1. 多周期均线趋势信号生成

多周期均线趋势信号生成 学习卡片

任务目标

基于同一只股票的日线、周线、月线收盘价,分别计算各自周期的均线(MA5、MA10、MA20),通过判断均线多头排列(MA5 > MA10 > MA20)生成趋势信号。当日线、周线、月线同时满足多头排列时,输出信号为1(强趋势);否则为0。最终输出包含原始价格与信号序列的DataFrame,并保存为CSV文件。

环境与依赖

需要 pandas、numpy。数据使用本地CSV文件,包含日期与日线收盘价。周线与月线数据由日线重采样生成,无需额外数据源。

关键完整代码

import pandas as pd
import numpy as np

def resample_ohlc(df, rule):
    """将日线数据重采样为周线或月线OHLC数据"""
    resampled = df.resample(rule).agg({
        'open': 'first',
        'high': 'max',
        'low': 'min',
        'close': 'last',
        'volume': 'sum'
    }).dropna()
    return resampled

def generate_trend_signal(df_daily):
    """
    输入:日线DataFrame,需包含列:date(datetime类型), open, high, low, close, volume
    输出:带趋势信号的DataFrame(按日线日期索引)
    """
    # 1. 重采样生成周线与月线
    df_weekly = resample_ohlc(df_daily, 'W')
    df_monthly = resample_ohlc(df_daily, 'M')

    # 2. 计算各周期均线
    for df in [df_daily, df_weekly, df_monthly]:
        df['MA5'] = df['close'].rolling(5).mean()
        df['MA10'] = df['close'].rolling(10).mean()
        df['MA20'] = df['close'].rolling(20).mean()

    # 3. 判断各周期多头排列(MA5 > MA10 > MA20)
    df_daily['daily_bull'] = (df_daily['MA5'] > df_daily['MA10']) & (df_daily['MA10'] > df_daily['MA20'])
    df_weekly['weekly_bull'] = (df_weekly['MA5'] > df_weekly['MA10']) & (df_weekly['MA10'] > df_weekly['MA20'])
    df_monthly['monthly_bull'] = (df_monthly['MA5'] > df_monthly['MA10']) & (df_monthly['MA10'] > df_monthly['MA20'])

    # 4. 将周线/月线信号对齐到日线日期(使用前向填充)
    df_daily['weekly_bull'] = df_weekly['weekly_bull'].reindex(df_daily.index, method='ffill')
    df_daily['monthly_bull'] = df_monthly['monthly_bull'].reindex(df_daily.index, method='ffill')

    # 5. 生成综合信号:三周期同时多头排列为1,否则为0
    df_daily['signal'] = ((df_daily['daily_bull']) &
                          (df_daily['weekly_bull']) &
                          (df_daily['monthly_bull'])).astype(int)

    # 6. 清理:删除均线计算产生的NaN行(前20日无完整MA20)
    result = df_daily.dropna(subset=['MA20']).copy()
    return result[['close', 'MA5', 'MA10', 'MA20', 'daily_bull', 'weekly_bull', 'monthly_bull', 'signal']]

# ========== 最小调用入口 ==========
if __name__ == '__main__':
    # 读取日线数据(示例:文件需包含 date,open,high,low,close,volume 列)
    df = pd.read_csv('daily_data.csv', parse_dates=['date'])
    df = df.set_index('date').sort_index()

    # 生成信号
    result = generate_trend_signal(df)

    # 输出信号序列
    print(result.tail(10))
    result.to_csv('trend_signal_output.csv', index=True)
    print('信号序列已保存至 trend_signal_output.csv')

运行与验证

运行方式:

  1. 准备日线CSV文件 daily_data.csv,必须包含列:date(格式如2024-01-01)、open、high、low、close、volume。数据需覆盖至少60个交易日(确保月线MA20有值)。
  2. 执行脚本:python trend_signal.py

验证方法:

  • 观察终端输出的最后10行,应包含 signal 列,取值为0或1。
  • 打开 trend_signal_output.csv,检查 signal 列是否存在且无NaN。
  • 手动抽查:任选一个信号为1的日期,确认该日期的日线MA5>MA10>MA20,且对应周线(该日所在周)与月线(该日所在月)的MA5>MA10>MA20均成立。
  • 信号为0的日期,至少有一个周期不满足多头排列。

预期输出示例(非实测):若某日三周期均线均呈多头排列,则当日 signal 为1;否则为0。由于均线计算需要前20个交易日数据,前20行输出中 signal 为NaN(已通过 dropna 去除),从第21个交易日开始有有效信号。

常见问题

  • 周线/月线信号对齐延迟:使用 ffill 前向填充,周线信号在周内每个交易日重复,月线信号在月内每个交易日重复。这是合理的近似处理,因为周/月均线在周期结束前不会更新。
  • 数据不足:若日线数据少于60个交易日,月线MA20将无值,导致所有信号为NaN。需确保数据量足够。
  • 日期索引:输入CSV的 date 列必须能被 parse_dates 正确解析,否则重采样会失败。