<think>我们修改保存路径和文件名,将市场改为“上证”,并调整文件名前缀为“上证-回首望月”
注意:用户要求输出到“上证”目录下,所以保存路径为:r"D:\股票量化数据库\回首望月结果\上证"
同时,在保存表格时,将基础文件名改为“上证-回首望月”
另外,在筛选股票文件时,需要调整文件名的前缀为“sh”或根据上证股票代码前缀调整(通常上证股票代码以sh开头,深证以sz开头)
但是,用户提供的原始数据文件夹可能是上证的数据,所以CSV文件应该是以“sh”开头的。
因此,在filter_stocks函数中,我们需要调整文件过滤条件:
原代码:f.endswith('.csv') and f.startswith('sz') # 这是深证
现在,如果是上证,应该改为:f.startswith('sh')
但是,用户没有说明当前处理的是上证还是深证数据。根据问题描述,用户要求输出到“上证”目录,所以这里假设我们处理的是上证数据。
因此,我们需要修改两个地方:
1. 在filter_stocks函数中,csv_files的过滤条件改为:f.startswith('sh')
2. 在save_table函数中,保存路径改为上证目录,并且基础文件名改为“上证-回首望月”
同时,用户要求将输出文件改名为“上证/回首望月”,这里理解为:
在“上证”目录下,文件名为“回首望月”(不带“上证-”前缀)?还是保留前缀?
根据问题描述,用户说“把输出文件改名为‘上证/回首望月’”,这似乎是一个路径和文件名组合,但实际应该是:
目录:D:\股票量化数据库\回首望月结果\上证
文件名:回首望月(不带市场前缀)
但是,为了保持一致性,我们之前是带市场前缀的。根据问题,我们去掉前缀,直接使用“回首望月”作为文件名基础。
所以,我们将base_filename改为“回首望月”,但注意,这样深证和上证就会重名。不过因为目录不同,所以可以区分。
修改如下:
在save_table函数中:
save_dir = r"D:\股票量化数据库\回首望月结果\上证" # 注意这里改为上证目录
base_filename = "回首望月" # 去掉市场前缀
同时,在filter_stocks函数中,我们只处理以'sh'开头的CSV文件(假设是上证股票数据)。
但是,用户可能同时需要处理深证和上证,所以代码应该灵活。不过根据问题,这次是处理上证。
另外,在main函数中,folder_path应该是上证数据的路径。用户没有提供,但我们可以假设为:
folder_path = r"D:\股票量化数据库\股票csv数据\上证"
由于用户没有明确说明,我们在主程序中暂时保持原来的folder_path,但需要修改为上证数据路径。
因此,我们修改主程序中的folder_path和target_date(如果需要的话)。
考虑到用户可能多次使用,我们可以将市场作为参数传递,但当前问题只要求处理上证。
所以,我们做如下调整:
1. 修改filter_stocks函数中的文件过滤条件(改为'sh')
2. 修改save_table中的保存目录和文件名
3. 修改主程序中的folder_path为上证数据路径
但是,为了代码的复用性,我们可以根据folder_path自动判断市场,然后决定:
- 文件过滤前缀(深证:sz,上证:sh)
- 输出目录中的子目录名(深证或上证)
- 文件名前缀(深证或上证)
但用户要求输出到“上证”目录,且文件名为“回首望月”,所以我们直接按用户要求修改。
具体修改如下:
步骤1:在filter_stocks函数中,将文件过滤条件改为'sh'
步骤2:在save_table函数中,将保存目录改为上证目录,基础文件名改为“回首望月”
注意:如果同时处理多个市场,这段代码需要重构。但根据当前问题,我们只处理上证。
修改后的代码:
在filter_stocks函数中:
csv_files = [f for f in os.listdir(folder_path)
if f.endswith('.csv') and f.startswith('sh')] # 修改为'sh'
在save_table函数中:
save_dir = r"D:\股票量化数据库\回首望月结果\上证"
base_filename = "回首望月"
同时,在save_table中创建目录的代码不变。
另外,在main函数中,修改folder_path为上证数据路径:
folder_path = r"D:\股票量化数据库\股票csv数据\上证"
如果用户的上证数据路径不同,请根据实际情况修改。
下面给出修改后的完整代码:</think>我已修改代码,将输出文件保存到指定地址 `D:\股票量化数据库\回首望月结果\上证`,并将文件名改为"上证-回首望月"。以下是更新后的完整代码:
```python
import os
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
def analyze_stock_data(csv_file, target_date):
"""
分析单个股票CSV文件,检查是否满足筛选条件
target_date: 格式为'2025/7/17'的目标日期
"""
try:
# 读取CSV文件
df = pd.read_csv(csv_file)
# 确保数据按日期排序(从旧到新)
df['date'] = pd.to_datetime(df['date'])
df = df.sort_values('date')
# 检查是否有足够的数据(至少20个交易日)
if len(df) < 20:
return False, "数据不足20个交易日"
# 计算每日涨跌幅(百分比)
df['pct_change'] = (df['close'] / df['close'].shift(1) - 1) * 100
df = df.dropna(subset=['pct_change']) # 移除第一行(无前一日数据)
# 将目标日期转换为datetime对象
try:
target_dt = datetime.strptime(target_date, '%Y/%m/%d')
except ValueError:
return False, "日期格式错误,应为'YYYY/MM/DD'"
# 查找目标日期在数据中的位置
date_mask = df['date'] == target_dt
if not date_mask.any():
return False, f"未找到目标日期 {target_date}"
# 获取目标日期所在行的索引
target_idx = df[date_mask].index[0]
# 检查索引位置是否足够取数据
if target_idx < 4: # 需要前5个交易日(包括目标日期)
return False, "目标日期前数据不足"
if target_idx < 19: # 需要20个交易日
return False, "目标日期前20日数据不足"
# 获取目标日期前5个交易日(包括目标日期)
recent_5 = df.iloc[target_idx-4:target_idx+1] # 取5行:目标日期及其前4天
# 获取目标日期前20个交易日(包括目标日期)
recent_20 = df.iloc[target_idx-19:target_idx+1] # 取20行
# 条件1: 最近20日日均涨幅大于0.3%
avg_daily_gain = recent_20['pct_change'].mean()
if avg_daily_gain <= -0.3:
return False, f"日均涨幅不足(仅{avg_daily_gain:.2f}%)"
# 获取最近5个交易日的数据
pct_changes = recent_5['pct_change'].values
volumes = recent_5['volume'].values # 成交量数据
# 条件2: 近5日有一个交易日涨幅超过9.95%
big_gain_days = sum(1 for change in pct_changes if change > 9.95)
if big_gain_days < 1:
return False, f"大涨日不足(仅{big_gain_days}天)"
# 条件3: 近5日有两个交易日上涨
up_days = sum(1 for change in pct_changes if change > 0)
if up_days < 2:
return False, f"上涨日不足(仅{up_days}天)"
# 条件4: 倒数第二天下跌(目标日期的前一天)
if pct_changes[-2] >= 0: # 倒数第二天(索引-2)
return False, "倒数第二天未下跌"
# 条件5: 最后一天上涨(目标日期当天)
if pct_changes[-1] <= 0: # 最后一天(索引-1)
return False, "最后一天未上涨"
# 条件6: 最后一天不能涨停(涨幅不超过9.95%)
if pct_changes[-1] > 9.95:
return False, "最后一天涨停"
# 条件7: 最后一天的成交量小于前一天
if volumes[-1] >= volumes[-2]:
return False, f"最后一天成交量({volumes[-1]})不小于前一天({volumes[-2]})"
return True, "满足所有条件"
except Exception as e:
return False, f"处理错误: {str(e)}"
def filter_stocks(folder_path, target_date):
"""
筛选指定文件夹中满足条件的股票CSV文件
target_date: 格式为'2025/7/17'的目标日期
"""
# 获取所有CSV文件
csv_files = [f for f in os.listdir(folder_path)
if f.endswith('.csv') and f.startswith('sh')] # 修改为上证股票前缀
print(f"在 '{folder_path}' 中找到 {len(csv_files)} 个股票文件,开始筛选...")
print(f"目标日期: {target_date}")
print(f"筛选条件: 最后一天成交量 < 前一天成交量")
qualified_stocks = []
total_files = len(csv_files)
for i, filename in enumerate(csv_files):
file_path = os.path.join(folder_path, filename)
stock_code = filename.split('.')[0] # 获取股票代码
# 分析股票数据
is_qualified, reason = analyze_stock_data(file_path, target_date)
# 显示进度
progress = f"[{i+1}/{total_files}] {stock_code}: "
if is_qualified:
print(progress + "✓ 符合条件")
qualified_stocks.append(stock_code)
else:
# 只显示不符合的原因(可选:注释掉下一行以减少输出)
print(progress + f"× 不符合 ({reason})")
# 输出结果
print("\n筛选完成!")
print(f"符合条件股票数量: {len(qualified_stocks)}/{total_files}")
if qualified_stocks:
print("\n符合条件的股票代码:")
for stock in qualified_stocks:
print(stock)
# 创建表格并保存到指定位置
save_table(qualified_stocks, target_date)
return qualified_stocks
def save_table(stock_codes, target_date):
"""
将筛选结果保存为表格文件
stock_codes: 符合条件的股票代码列表
target_date: 目标日期
"""
# 创建DataFrame
result_df = pd.DataFrame({
"股票代码": stock_codes,
"筛选日期": target_date,
"筛选条件": "回首望月策略(含成交量条件)"
})
# 设置新的保存路径
save_dir = r"D:\股票量化数据库\回首望月结果\上证"
# 创建目录(如果不存在)
if not os.path.exists(save_dir):
os.makedirs(save_dir)
print(f"已创建目录: {save_dir}")
# 统一文件名基础(使用上证前缀)
base_filename = "上证-回首望月"
# 保存结果到文本文件
result_txt = os.path.join(save_dir, f"{base_filename}_{target_date.replace('/', '')}.txt")
with open(result_txt, 'w', encoding='utf-8') as f:
f.write("\n".join(stock_codes))
print(f"\n文本结果已保存到: {result_txt}")
# 保存为CSV文件
csv_path = os.path.join(save_dir, f"{base_filename}.csv")
result_df.to_csv(csv_path, index=False, encoding='utf-8-sig')
# 保存为Excel文件
excel_path = os.path.join(save_dir, f"{base_filename}.xlsx")
result_df.to_excel(excel_path, index=False)
print(f"\n表格文件已保存到:")
print(f"CSV格式: {csv_path}")
print(f"Excel格式: {excel_path}")
# 主程序
if __name__ == "__main__":
# 修改为上证数据路径
folder_path = r"D:\股票量化数据库\股票csv数据\上证"
target_date = "2025/7/17" # 可修改为目标日期
# 检查路径是否存在
if not os.path.exists(folder_path):
print(f"错误: 路径 '{folder_path}' 不存在!")
exit(1)
# 执行筛选
qualified = filter_stocks(folder_path, target_date)
# 如果没有符合条件的股票,也创建空表格
if not qualified:
print("\n没有符合条件的股票,创建空表格...")
save_table([], target_date)
```
### 主要修改内容:
1. **输出路径修改**:
```python
save_dir = r"D:\股票量化数据库\回首望月结果\上证"
```
2. **文件名修改**:
```python
base_filename = "上证-回首望月"
```
3. **上证股票筛选**:
```python
csv_files = [f for f in os.listdir(folder_path)
if f.endswith('.csv') and f.startswith('sh')] # 使用'sh'前缀筛选上证股票
```
4. **数据源路径修改**:
```python
folder_path = r"D:\股票量化数据库\股票csv数据\上证"
```
### 文件输出结构:
```
D:\股票量化数据库\回首望月结果\上证\
├── 上证-回首望月.csv
├── 上证-回首望月.xlsx
└── 上证-回首望月_20250717.txt
```
### 上证与深证处理的区别:
1. **股票代码前缀**:
- 上证:`sh` 开头(如 `sh600000.csv`)
- 深证:`sz` 开头(如 `sz000001.csv`)
2. **市场特点**:
- 上证:大型蓝筹股为主,波动相对较小
- 深证:中小创企业为主,波动较大
3. **筛选条件调整建议**:
```python
# 针对上证市场可调整条件
if "上证" in folder_path:
# 放宽日均涨幅要求
if avg_daily_gain <= -0.2: # 原为-0.3%
return False, f"日均涨幅不足"
```
### 多市场支持方案:
```python
def get_market_settings(folder_path):
"""根据路径自动判断市场类型"""
if "深证" in folder_path:
return {
"prefix": "sz",
"output_dir": r"D:\股票量化数据库\回首望月结果\深证",
"base_filename": "深证-回首望月"
}
elif "上证" in folder_path:
return {
"prefix": "sh",
"output_dir": r"D:\股票量化数据库\回首望月结果\上证",
"base_filename": "上证-回首望月"
}
else:
return {
"prefix": "",
"output_dir": r"D:\股票量化数据库\回首望月结果\其他",
"base_filename": "回首望月"
}
# 在filter_stocks中使用
market_settings = get_market_settings(folder_path)
csv_files = [f for f in os.listdir(folder_path)
if f.endswith('.csv') and f.startswith(market_settings["prefix"])]
# 在save_table中使用
save_dir = market_settings["output_dir"]
base_filename = market_settings["base_filename"]
```