import baostock as bs
import pandas as pd
from datetime import datetime, timedelta
import time
import logging
import sys
# 配置logging模块
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
# 登录baostock系统
def login_baostock():
lg = bs.login()
if lg.error_code != '0':
print("登录失败:", lg.error_msg)
exit()
return lg
# 获取最近一个交易日
def get_last_trade_date():
today = datetime.now().strftime("%Y-%m-%d")
trade_dates = bs.query_trade_dates(start_date=today, end_date=today).get_data()
if trade_dates.empty or trade_dates.iloc[0]['is_trading_day'] == '0':
# 如果当天不是交易日,向前推算
last_trade_date = bs.query_trade_dates(
start_date=(datetime.now() - timedelta(days=10)).strftime("%Y-%m-%d"),
end_date=today
).get_data()
last_trade_date = last_trade_date[last_trade_date['is_trading_day'] == '1'].iloc[-1]['calendar_date']
else:
last_trade_date = today
return last_trade_date
# 获取当前日期的前一个交易日
def get_last_trade_date_yesterday():
# 获取昨天的日期
yesterday = (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d')
trade_dates = bs.query_trade_dates(start_date=yesterday, end_date=yesterday).get_data()
if trade_dates.empty or trade_dates.iloc[0]['is_trading_day'] == '0':
# 如果当天不是交易日,向前推算
last_trade_date = bs.query_trade_dates(
start_date=(datetime.now() - timedelta(days=10)).strftime("%Y-%m-%d"),
end_date=yesterday
).get_data()
last_trade_date = last_trade_date[last_trade_date['is_trading_day'] == '1'].iloc[-1]['calendar_date']
else:
last_trade_date = yesterday
return last_trade_date
def is_before_6pm():
now = datetime.now()
current_hour = now.hour
return current_hour < 18
def get_trade_date():
if is_before_6pm():
# 小于当天18点,取前一天。baostock库交易日18时之前,日 K 数据还未入库,所以找前一天。
last_trade_date = get_last_trade_date_yesterday()
else:
# 大于当天18点,交易日取前当天
last_trade_date = get_last_trade_date()
return last_trade_date
# 获取所有A股股票代码(剔除指数代码)
def get_all_stock_codes(last_trade_date):
rs = bs.query_all_stock(day=last_trade_date) # 使用最近一个交易日获取股票列表
stock_list = []
while (rs.error_code == '0') & rs.next():
stock_code = rs.get_row_data()[0] # 股票代码格式如:sh.600000
# 剔除指数代码(指数代码通常以 sh.000 或 sz.399 开头)
if not (stock_code.startswith("sh.000") or stock_code.startswith("sz.399")):
stock_list.append(stock_code)
return stock_list
# 获取股票名称
def get_stock_name(stock_code):
stock_info = bs.query_stock_basic(code=stock_code).get_data()
if stock_info.empty:
return None
if 'code_name' in stock_info.columns: # baostock返回的字段可能是code_name
return stock_info.iloc[0]['code_name']
elif 'stock_name' in stock_info.columns: # 也可能是stock_name
return stock_info.iloc[0]['stock_name']
return None
# 剔除不符合条件的股票(北交所、科创板、ST股票)
def filter_stock(stock_code):
# 剔除北交所股票(代码以 bj. 开头)
if stock_code.startswith("bj."):
return False
# 剔除科创板股票(代码以 sh.688 开头)
if stock_code.startswith("sh.688"):
return False
# 获取股票名称并剔除ST股票
stock_name = get_stock_name(stock_code)
# print(f"stock_name:{stock_name}")
if stock_name is None:
return False
if "ST" in stock_name or "*ST" in stock_name:
return False
return True
# 获取前第4个交易日
def get_before_trade_date_by_loop(today_date):
dates = []
# 初始化变量i
i = 0
before_trade_date = today_date
# 设置循环的结束条件
while i < 3:
# 执行循环体内的代码
before_trade_date = get_before_trade_date(before_trade_date)
# print(i)
# i自加
i += 1
dates.append(before_trade_date)
return dates
# 计算最近四个交易日的成交量是否符合条件
def calculate_volume_multiple(stock_code, last_trade_date):
# 获取最近四个交易日的日期
trade_dates = bs.query_trade_dates(
start_date=(datetime.strptime(last_trade_date, "%Y-%m-%d") - timedelta(days=10)).strftime("%Y-%m-%d"),
end_date=last_trade_date
).get_data()
trade_dates = trade_dates[trade_dates['is_trading_day'] == '1'].tail(4)['calendar_date'].tolist()
if len(trade_dates) < 4:
logging.warning(f"Not enough trading days for {stock_code}")
return None
# 查询最近四个交易日的成交量
k_data = bs.query_history_k_data_plus(
code=stock_code,
fields="date,volume",
start_date=trade_dates[0],
end_date=last_trade_date,
frequency="d",
adjustflag="3"
).get_data()
if k_data.empty or len(k_data) < 4:
logging.warning(f"No data or insufficient data for {stock_code}")
return None
# 提取最近四个交易日的成交量数据
volumes = {}
for date in trade_dates:
date_data = k_data[k_data['date'] == date]
if date_data.empty:
logging.warning(f"Missing data for {stock_code} on {date}")
return None
volumes[date] = float(date_data.iloc[0]['volume'])
# 检查成交量条件
if volumes[trade_dates[2]] / volumes[trade_dates[3]] < 3:
return None
if volumes[trade_dates[1]] < volumes[trade_dates[2]] * 0.8:
return None
if volumes[trade_dates[0]] < volumes[trade_dates[2]] * 0.8:
return None
# 获取股票名称
stock_name = get_stock_name(stock_code)
if stock_name is None:
logging.warning(f"Failed to get stock name for {stock_code}")
return None
return {
"股票代码": stock_code,
"股票名称": stock_name,
"目标日期": last_trade_date,
"倒数第三个交易日成交量": str(round(volumes[trade_dates[2]] / 1000000, 2)) + "万手",
"倒数第二个交易日成交量": str(round(volumes[trade_dates[1]] / 1000000, 2)) + "万手",
"最近一个交易日成交量": str(round(volumes[trade_dates[0]] / 1000000, 2)) + "万手"
}
# 计算成交量放大倍数
def calculate_volume_multiple_last4days(stock_code, today, yesterday, before, forth, iv_param, pcent):
# 获取股票名称
stock_name = get_stock_name(stock_code)
if stock_name is None:
return None
# print(f"calculate_volume_multiple ====== stock_code is {stock_code}")
# 查询目标日期和之前5天的数据,一共6天的数据
k_data = bs.query_history_k_data_plus(
code=stock_code,
fields="date,volume,pctChg",
start_date=forth,
end_date=today,
frequency="d",
adjustflag="3"
).get_data()
# print(f"calculate_volume_multiple ====== k_data is {k_data}")
# 检查是否有数据,以及成交量是否为空,数据天数不少于4天
if k_data.empty or len(k_data) < 4:
logging.warning(f"No data or insufficient data for {stock_code}")
return None # 跳过无数据或停牌的股票
# 提取今天的成交量数据
today_data = k_data[k_data['date'] == today]
# 提取昨天的成交量数据
yesterday_data = k_data[k_data['date'] == yesterday]
# 提取前天的成交量数据
before_data = k_data[k_data['date'] == before]
# 提取前三天的成交量数据
forth_data = k_data[k_data['date'] == forth]
# 检查今天和昨天的成交量数据是否有效
if today_data.empty or yesterday_data.empty or before_data.empty or forth_data.empty:
logging.warning(
f"Missing data for {stock_code}: start_date={forth}, before={before}, yesterday={yesterday}, end_date={today}")
return None # 跳过数据缺失的情况
# 当日的数据
today_volume = today_data.iloc[0]['volume']
yesterday_volume = yesterday_data.iloc[0]['volume']
before_volume = before_data.iloc[0]['volume']
forth_volume = forth_data.iloc[0]['volume']
# 最近两日停牌的票
if today_volume == '' or yesterday_volume == '':
logging.error(f"{stock_code}:停牌!")
logging.error(f"Empty volume data for {stock_code}: yesterday={yesterday_volume}, today={today_volume}")
logging.error(f"Empty volume data for {stock_code}: yesterday={yesterday_volume}, today={today_volume}")
# 检查成交量是否为空字符串
if today_volume == '' or yesterday_volume == '' or before_volume == '' or forth_volume == '':
logging.warning(
f"Empty volume data for {stock_code}: forth={forth_volume}, before={before_volume}, yesterday={yesterday_volume}, today={today_volume}")
return None # 跳过无效数据
# 将成交量转换为浮点数
try:
current_volume = float(today_volume)
yesterday_volume = float(yesterday_volume)
before_volume = float(before_volume)
forth_volume = float(forth_volume)
except ValueError as e:
logging.error(f"Failed to convert volume to float for {stock_code}: {e}")
return None # 跳过无法转换的数据
# 计算成交量放大倍数
if forth_volume == 0:
logging.warning(f"forth volume is zero for {stock_code}")
return None # 避免除以零
before_volume_multiple = before_volume / forth_volume
# 检查成交量条件
if before_volume_multiple < iv_param:
return None
if yesterday_volume < before_volume * pcent:
return None
if current_volume < yesterday_volume * pcent:
return None
current_date = today_data.iloc[0]['date']
# 涨跌幅(百分比) 日涨跌幅 = [(指定交易日的收盘价 - 指定交易日前收盘价) / 指定交易日前收盘价] * 100 %
current_pctChg = today_data.iloc[0]['pctChg']
yesterday_pctChg = yesterday_data.iloc[0]['pctChg']
# volume 成交量(累计 单位:股) 万手要处理 6 位数
wanshou = "万手"
forth_volume_string = str(round(forth_volume / 1000000, 2)) + wanshou
before_volume_string = str(round(before_volume / 1000000, 2)) + wanshou
yesterday_volume_string = str(round(yesterday_volume / 1000000, 2)) + wanshou
current_volume_string = str(round(current_volume / 1000000, 2)) + wanshou
return {
"stock_code": stock_code,
"stock_name": stock_name,
"target_date": current_date,
"forth_volume": forth_volume_string,
"before_volume": before_volume_string,
"yesterday_volume": yesterday_volume_string,
"current_volume": current_volume_string,
"compare_before_multiple": round(before_volume_multiple, 2),
"current_pctChg": current_pctChg,
"yesterday_pctChg": yesterday_pctChg,
}
# 获取前一天的交易日
def get_before_trade_date(today_date):
# 获取昨天的日期
yesterday_date = (datetime.strptime(today_date, "%Y-%m-%d") - timedelta(days=1)).strftime("%Y-%m-%d")
# 检查昨天是否是交易日
trade_dates = bs.query_trade_dates(start_date=yesterday_date, end_date=yesterday_date).get_data()
if trade_dates.empty or trade_dates.iloc[0]['is_trading_day'] == '0':
print(f"yesterday_date is {yesterday_date}, {yesterday_date}不是交易日,往前迭代一天。")
return get_before_trade_date(yesterday_date)
else:
return yesterday_date
####################################################### 主程序 #########################################################
####################################################### 主程序 #########################################################
####################################################### 主程序 #########################################################
def main():
argv = sys.argv
print(f"完整python命令为:{argv},len(argv):{len(argv)}")
# 放量倍数
iv_param = 3
# 今日是前一日的占比
pcent = 0.8
# 登录baostock
login_baostock()
logging.info("程序执行时间...小于当天18时,取前一个交易日,大与18时,采取当前天。")
# 获取最近一个交易日
today = get_target_date_by_param(argv)
dates = get_before_trade_date_by_loop(today)
yesterday = dates[0]
before = dates[1]
forth = dates[2]
print(f"today:{today}, yesterday:{dates[0]}, before:{dates[1]}, forth:{dates[2]}")
# 获取所有A股股票代码(剔除指数代码)
stock_list = get_all_stock_codes(today)
# 使用切片来获取前十条元素
# 注意:如果列表长度小于10,这会返回整个列表
# first_ten = stock_list[:5]
# print(first_ten)
# 筛选符合条件的股票
result = []
for code in stock_list:
if not filter_stock(code):
continue
volume_data = calculate_volume_multiple_last4days(code, today, yesterday, before, forth, iv_param, pcent)
if volume_data:
result.append(volume_data)
# 将结果转换为DataFrame并排序
if result:
df_result = pd.DataFrame(result)
df_result = df_result.sort_values(by=["current_pctChg", "compare_before_multiple"], ascending=False) # 按最近一个交易日成交量倒序排序
# 输出到Excel文件
local_path = "D:/name/tools/bat/consecutive3days/files"
output_file = f"{local_path}/{today}_成交量连续三天放大.xlsx"
df_result.to_excel(output_file, index=False)
print(f"结果已保存到文件: {output_file}")
else:
print("未找到符合条件的股票。")
# 登出系统
bs.logout()
def main3():
argv = sys.argv
print(f"完整python命令为:{argv},len(argv):{len(argv)}")
# 登录baostock
login_baostock()
logging.info("程序执行时间...小于当天18时,取前一个交易日,大与18时,采取当前天。")
# 获取最近一个交易日
last_trade_date = get_target_date_by_param(argv)
# 获取所有A股股票代码(剔除指数代码)
stock_list = get_all_stock_codes(last_trade_date)
# 筛选符合条件的股票
result = []
for code in stock_list:
if not filter_stock(code):
continue
volume_data = calculate_volume_multiple(code, last_trade_date)
if volume_data:
result.append(volume_data)
# 将结果转换为DataFrame并排序
if result:
df_result = pd.DataFrame(result)
df_result = df_result.sort_values(by=["最近一个交易日成交量"], ascending=False) # 按最近一个交易日成交量倒序排序
# 输出到Excel文件
local_path = "D:/name/tools/bat/volumeIncrease"
output_file = f"{local_path}/{last_trade_date}_成交量放大条件股票.xlsx"
df_result.to_excel(output_file, index=False)
print(f"结果已保存到文件: {output_file}")
else:
print("未找到符合条件的股票。")
# 登出系统
bs.logout()
# 有输入日期,取日期的,默认取最近交易日的。
def get_target_date_by_param(argv):
if len(argv) > 1 and argv[1] != '':
logging.warning("当前取输入参数为目标日期! 注意日期输入格式 %Y-%m-%d !")
target_date = argv[1]
else:
logging.warning("当前取最近交易日为目标日期! ")
target_date = get_trade_date()
return target_date
def main2():
argv = sys.argv
print(f"完整python命令为:{argv},len(argv):{len(argv)}")
# 登录baostock
login_baostock()
target_date = get_target_date_by_param(argv)
dates = get_before_trade_date_by_loop(target_date)
# print(f"dates:{dates}")
print(f"today:{target_date}, yesterday:{dates[0]}, before:{dates[1]}, forth:{dates[2]}")
code = "sz.000488"
filter_stock(code)
# 程序入口
if __name__ == "__main__":
# 记录开始时间
start_time = time.time()
logging.info("程序开始执行...")
logging.info("程序信息:计算股票成交量,相对昨天放量的情况!")
main()
# 记录另一条信息日志
logging.info("程序执行完成。")
# 记录结束时间
end_time = time.time()
# 计算并打印执行时长
logging.info(f"执行时长: {str(round((end_time - start_time) / 60, 2))} 分钟")
Python查询连续三天成交量较前5天平均值
于 2025-02-11 22:30:06 首次发布
部署运行你感兴趣的模型镜像
您可能感兴趣的与本文相关的镜像
Python3.10
Conda
Python
Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本
1673

被折叠的 条评论
为什么被折叠?



