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')
运行与验证
运行方式:
- 准备日线CSV文件
daily_data.csv,必须包含列:date(格式如2024-01-01)、open、high、low、close、volume。数据需覆盖至少60个交易日(确保月线MA20有值)。 - 执行脚本:
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正确解析,否则重采样会失败。