tushare
This commit is contained in:
+160
-86
@@ -329,11 +329,56 @@ class MarketSentimentDataFetcher:
|
||||
}
|
||||
|
||||
def _get_turnover_rate(self, symbol):
|
||||
"""获取换手率数据(支持akshare和tushare自动切换)"""
|
||||
"""获取换手率数据(优先tushare,失败时使用akshare)"""
|
||||
try:
|
||||
# 优先使用akshare获取最近的换手率数据
|
||||
print(f" [Akshare] 正在获取换手率数据...")
|
||||
# 获取A股实时行情数据(不需要参数)
|
||||
# 优先使用tushare(daily_basic,取最近10个交易日保证非交易日也有数据)
|
||||
if data_source_manager.tushare_available:
|
||||
try:
|
||||
print(f" [Tushare] 正在获取换手率数据(主要数据源)...")
|
||||
ts_code = data_source_manager._convert_to_ts_code(symbol)
|
||||
|
||||
end_date = datetime.now().strftime('%Y%m%d')
|
||||
start_date = (datetime.now() - timedelta(days=10)).strftime('%Y%m%d')
|
||||
df = data_source_manager.tushare_api.daily_basic(
|
||||
ts_code=ts_code,
|
||||
start_date=start_date,
|
||||
end_date=end_date
|
||||
)
|
||||
|
||||
if df is not None and not df.empty:
|
||||
row = df.iloc[0]
|
||||
turnover_rate = row.get('turnover_rate', 'N/A')
|
||||
|
||||
# 解读换手率
|
||||
interpretation = ""
|
||||
if turnover_rate != 'N/A':
|
||||
try:
|
||||
turnover = float(turnover_rate)
|
||||
if turnover > 20:
|
||||
interpretation = "换手率极高(>20%),资金活跃度极高,可能存在炒作"
|
||||
elif turnover > 10:
|
||||
interpretation = "换手率较高(>10%),交易活跃"
|
||||
elif turnover > 5:
|
||||
interpretation = "换手率正常(5%-10%),交易适中"
|
||||
elif turnover > 2:
|
||||
interpretation = "换手率偏低(2%-5%),交易相对清淡"
|
||||
else:
|
||||
interpretation = "换手率很低(<2%),交易清淡"
|
||||
except:
|
||||
pass
|
||||
|
||||
print(f" [Tushare] ✅ 成功获取换手率: {turnover_rate}%")
|
||||
return {
|
||||
"current_turnover_rate": turnover_rate,
|
||||
"interpretation": interpretation
|
||||
}
|
||||
else:
|
||||
print(f" [Tushare] ❌ 未获取到换手率,尝试备用数据源")
|
||||
except Exception as te:
|
||||
print(f" [Tushare] ❌ 获取失败: {te}")
|
||||
|
||||
# tushare失败,回退akshare
|
||||
print(f" [Akshare] 正在获取换手率数据(备用数据源)...")
|
||||
df = ak.stock_zh_a_spot_em()
|
||||
if df is not None and not df.empty:
|
||||
stock_data = df[df['代码'] == symbol]
|
||||
@@ -366,57 +411,42 @@ class MarketSentimentDataFetcher:
|
||||
}
|
||||
except Exception as e:
|
||||
print(f" [Akshare] ❌ 获取换手率失败: {e}")
|
||||
|
||||
# akshare失败,尝试tushare
|
||||
if data_source_manager.tushare_available:
|
||||
try:
|
||||
print(f" [Tushare] 正在获取换手率数据(备用数据源)...")
|
||||
ts_code = data_source_manager._convert_to_ts_code(symbol)
|
||||
|
||||
# 获取最近一个交易日的数据
|
||||
df = data_source_manager.tushare_api.daily_basic(
|
||||
ts_code=ts_code,
|
||||
trade_date=datetime.now().strftime('%Y%m%d')
|
||||
)
|
||||
|
||||
if df is not None and not df.empty:
|
||||
row = df.iloc[0]
|
||||
turnover_rate = row.get('turnover_rate', 'N/A')
|
||||
|
||||
# 解读换手率
|
||||
interpretation = ""
|
||||
if turnover_rate != 'N/A':
|
||||
try:
|
||||
turnover = float(turnover_rate)
|
||||
if turnover > 20:
|
||||
interpretation = "换手率极高(>20%),资金活跃度极高,可能存在炒作"
|
||||
elif turnover > 10:
|
||||
interpretation = "换手率较高(>10%),交易活跃"
|
||||
elif turnover > 5:
|
||||
interpretation = "换手率正常(5%-10%),交易适中"
|
||||
elif turnover > 2:
|
||||
interpretation = "换手率偏低(2%-5%),交易相对清淡"
|
||||
else:
|
||||
interpretation = "换手率很低(<2%),交易清淡"
|
||||
except:
|
||||
pass
|
||||
|
||||
print(f" [Tushare] ✅ 成功获取换手率: {turnover_rate}%")
|
||||
return {
|
||||
"current_turnover_rate": turnover_rate,
|
||||
"interpretation": interpretation
|
||||
}
|
||||
except Exception as te:
|
||||
print(f" [Tushare] ❌ 获取失败: {te}")
|
||||
|
||||
return None
|
||||
|
||||
def _get_market_index_sentiment(self):
|
||||
"""获取大盘指数情绪(支持akshare和tushare自动切换)"""
|
||||
try:
|
||||
# 优先使用akshare获取上证指数实时数据
|
||||
print(f" [Akshare] 正在获取大盘指数数据...")
|
||||
# 使用正确的symbol参数
|
||||
# 优先使用tushare(index_daily,取最近10个交易日保证非交易日也有数据)
|
||||
if data_source_manager.tushare_available:
|
||||
try:
|
||||
print(f" [Tushare] 正在获取大盘指数数据(主要数据源)...")
|
||||
|
||||
# 获取上证指数数据
|
||||
end_date = datetime.now().strftime('%Y%m%d')
|
||||
start_date = (datetime.now() - timedelta(days=10)).strftime('%Y%m%d')
|
||||
df = data_source_manager.tushare_api.index_daily(
|
||||
ts_code='000001.SH',
|
||||
start_date=start_date,
|
||||
end_date=end_date
|
||||
)
|
||||
|
||||
if df is not None and not df.empty:
|
||||
row = df.iloc[0]
|
||||
change_pct = row.get('pct_chg', 0)
|
||||
|
||||
print(f" [Tushare] ✅ 成功获取大盘指数涨跌幅: {change_pct}%")
|
||||
return {
|
||||
"index_name": "上证指数",
|
||||
"change_percent": change_pct
|
||||
}
|
||||
else:
|
||||
print(f" [Tushare] ❌ 未获取到大盘指数,尝试备用数据源")
|
||||
except Exception as te:
|
||||
print(f" [Tushare] ❌ 获取失败: {te}")
|
||||
|
||||
# tushare失败,回退akshare
|
||||
print(f" [Akshare] 正在获取大盘指数数据(备用数据源)...")
|
||||
df = ak.stock_zh_index_spot_em(symbol="上证系列指数")
|
||||
if df is not None and not df.empty:
|
||||
# 查找上证指数(代码为000001)
|
||||
@@ -470,30 +500,6 @@ class MarketSentimentDataFetcher:
|
||||
}
|
||||
except Exception as e:
|
||||
print(f" [Akshare] ❌ 获取大盘指数失败: {e}")
|
||||
|
||||
# akshare失败,尝试tushare
|
||||
if data_source_manager.tushare_available:
|
||||
try:
|
||||
print(f" [Tushare] 正在获取大盘指数数据(备用数据源)...")
|
||||
|
||||
# 获取上证指数数据
|
||||
df = data_source_manager.tushare_api.index_daily(
|
||||
ts_code='000001.SH',
|
||||
start_date=datetime.now().strftime('%Y%m%d'),
|
||||
end_date=datetime.now().strftime('%Y%m%d')
|
||||
)
|
||||
|
||||
if df is not None and not df.empty:
|
||||
row = df.iloc[0]
|
||||
change_pct = row.get('pct_chg', 0)
|
||||
|
||||
print(f" [Tushare] ✅ 成功获取大盘指数涨跌幅: {change_pct}%")
|
||||
return {
|
||||
"index_name": "上证指数",
|
||||
"change_percent": change_pct
|
||||
}
|
||||
except Exception as te:
|
||||
print(f" [Tushare] ❌ 获取失败: {te}")
|
||||
|
||||
return None
|
||||
|
||||
@@ -503,19 +509,50 @@ class MarketSentimentDataFetcher:
|
||||
# 获取今日涨停和跌停统计
|
||||
today = datetime.now().strftime('%Y%m%d')
|
||||
|
||||
# 获取涨停股票
|
||||
try:
|
||||
limit_up_df = ak.stock_zt_pool_em(date=today)
|
||||
limit_up_count = len(limit_up_df) if limit_up_df is not None and not limit_up_df.empty else 0
|
||||
except:
|
||||
limit_up_count = 0
|
||||
limit_up_count = 0
|
||||
limit_down_count = 0
|
||||
|
||||
# 获取跌停股票
|
||||
try:
|
||||
limit_down_df = ak.stock_zt_pool_dtgc_em(date=today)
|
||||
limit_down_count = len(limit_down_df) if limit_down_df is not None and not limit_down_df.empty else 0
|
||||
except:
|
||||
limit_down_count = 0
|
||||
# 优先使用tushare的涨跌停列表
|
||||
if data_source_manager.tushare_available:
|
||||
try:
|
||||
print(f" [Tushare] 正在获取涨跌停数据(主要数据源)...")
|
||||
df_ll = data_source_manager.tushare_api.limit_list_d(trade_date=today)
|
||||
if df_ll is not None and not df_ll.empty:
|
||||
if 'limit_type' in df_ll.columns:
|
||||
limit_up_count = int((df_ll['limit_type'].fillna('') == 'U').sum())
|
||||
limit_down_count = int((df_ll['limit_type'].fillna('') == 'D').sum())
|
||||
print(f" [Tushare] ✅ 成功获取涨跌停: 涨停{limit_up_count} / 跌停{limit_down_count}")
|
||||
elif 'pct_chg' in df_ll.columns:
|
||||
limit_up_count = int((df_ll['pct_chg'] >= 9.5).sum())
|
||||
limit_down_count = int((df_ll['pct_chg'] <= -9.5).sum())
|
||||
print(f" [Tushare] ✅ 成功获取涨跌停: 涨停{limit_up_count} / 跌停{limit_down_count}")
|
||||
elif '涨跌幅' in df_ll.columns:
|
||||
limit_up_count = int((df_ll['涨跌幅'] >= 9.5).sum())
|
||||
limit_down_count = int((df_ll['涨跌幅'] <= -9.5).sum())
|
||||
print(f" [Tushare] ✅ 成功获取涨跌停: 涨停{limit_up_count} / 跌停{limit_down_count}")
|
||||
else:
|
||||
# 无法识别的列结构,按0处理并回退akshare
|
||||
print(f" [Tushare] ⚠ 涨跌停返回列无法识别: {list(df_ll.columns)[:10]},尝试备用数据源")
|
||||
else:
|
||||
print(f" [Tushare] ❌ 未获取到涨跌停数据,尝试备用数据源")
|
||||
except Exception as e:
|
||||
print(f" [Tushare] ❌ 获取涨跌停数据失败: {e}")
|
||||
|
||||
# tushare不可用或失败时,回退akshare
|
||||
if limit_up_count == 0 and limit_down_count == 0:
|
||||
# 获取涨停股票
|
||||
try:
|
||||
limit_up_df = ak.stock_zt_pool_em(date=today)
|
||||
limit_up_count = len(limit_up_df) if limit_up_df is not None and not limit_up_df.empty else 0
|
||||
except:
|
||||
limit_up_count = 0
|
||||
|
||||
# 获取跌停股票
|
||||
try:
|
||||
limit_down_df = ak.stock_zt_pool_dtgc_em(date=today)
|
||||
limit_down_count = len(limit_down_df) if limit_down_df is not None and not limit_down_df.empty else 0
|
||||
except:
|
||||
limit_down_count = 0
|
||||
|
||||
# 计算涨跌停比例
|
||||
if limit_up_count + limit_down_count > 0:
|
||||
@@ -549,6 +586,44 @@ class MarketSentimentDataFetcher:
|
||||
def _get_margin_trading_data(self, symbol):
|
||||
"""获取融资融券数据"""
|
||||
try:
|
||||
# 优先使用tushare的个股融资融券明细
|
||||
if data_source_manager.tushare_available:
|
||||
try:
|
||||
print(f" [Tushare] 正在获取融资融券数据(主要数据源)...")
|
||||
ts_code = data_source_manager._convert_to_ts_code(symbol)
|
||||
end_date = datetime.now().strftime('%Y%m%d')
|
||||
start_date = (datetime.now() - timedelta(days=15)).strftime('%Y%m%d')
|
||||
df = data_source_manager.tushare_api.margin_detail(
|
||||
ts_code=ts_code,
|
||||
start_date=start_date,
|
||||
end_date=end_date
|
||||
)
|
||||
if df is not None and not df.empty:
|
||||
latest = df.iloc[0]
|
||||
margin_balance = latest.get('rzye', 0) or 0
|
||||
short_balance = latest.get('rqye', 0) or 0
|
||||
|
||||
# 解读融资融券
|
||||
interpretation = []
|
||||
if margin_balance > short_balance * 10:
|
||||
interpretation.append("融资余额远大于融券余额,投资者看多情绪强")
|
||||
elif margin_balance > short_balance * 3:
|
||||
interpretation.append("融资余额大于融券余额,投资者偏看多")
|
||||
else:
|
||||
interpretation.append("融资融券相对平衡")
|
||||
|
||||
print(f" [Tushare] ✅ 成功获取融资融券数据")
|
||||
return {
|
||||
"margin_balance": margin_balance,
|
||||
"short_balance": short_balance,
|
||||
"interpretation": interpretation,
|
||||
"date": str(latest.get('trade_date', datetime.now().strftime('%Y-%m-%d')))
|
||||
}
|
||||
else:
|
||||
print(f" [Tushare] ❌ 未获取到融资融券数据,尝试备用数据源")
|
||||
except Exception as e:
|
||||
print(f" [Tushare] ❌ 获取融资融券数据失败: {e}")
|
||||
|
||||
# 获取个股融资融券数据(尝试多个API)
|
||||
try:
|
||||
# 方法1:获取沪深融资融券明细
|
||||
@@ -762,4 +837,3 @@ if __name__ == "__main__":
|
||||
print(formatted_text)
|
||||
else:
|
||||
print(f"\n获取失败: {sentiment_data.get('error', '未知错误')}")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user