Files
stock/stock-html/update_fundamental.py
T
freedakgmail 9c7d7abdd4 Initial commit
2026-07-17 18:49:35 +08:00

152 lines
4.2 KiB
Python

#!/usr/bin/env python3
"""
批量更新数据库中缺少财务指标的基本面数据
"""
import akshare as ak
import pandas as pd
import psycopg2
from datetime import date, datetime
import time
# 数据库配置
DB_CONFIG = {
'host': 'localhost',
'port': 5432,
'dbname': 'stock_app',
'user': 'postgres',
'password': 'xypg5432'
}
def get_db():
"""获取数据库连接"""
try:
conn = psycopg2.connect(**DB_CONFIG)
return conn
except Exception as e:
print(f"数据库连接失败: {e}")
return None
def get_stocks_need_update():
"""获取需要更新财务指标的股票列表"""
conn = get_db()
if not conn:
return []
try:
cur = conn.cursor()
cur.execute("""
SELECT code, name
FROM stock_fundamental
WHERE roe IS NULL OR eps IS NULL
""")
return cur.fetchall()
finally:
conn.close()
def fetch_financial_indicators(stock_code):
"""从akshare获取股票财务指标"""
try:
df = ak.stock_financial_analysis_indicator(symbol=stock_code, start_year='2024')
if df is None or df.empty:
return None
latest = df.iloc[-1]
def safe_float(val):
if pd.isna(val):
return None
try:
return float(val)
except:
return None
return {
'eps': safe_float(latest.get('摊薄每股收益(元)')),
'bps': safe_float(latest.get('每股净资产_调整后(元)')),
'roe': safe_float(latest.get('净资产收益率(%)')),
'gross_margin': safe_float(latest.get('销售毛利率(%)')),
'net_margin': safe_float(latest.get('销售净利率(%)')),
'revenue_yoy': safe_float(latest.get('主营业务收入增长率(%)')),
'profit_yoy': safe_float(latest.get('净利润增长率(%)')),
}
except Exception as e:
print(f" 获取 {stock_code} 财务指标失败: {e}")
return None
def update_stock_fundamental(stock_code, data):
"""更新股票基本面数据"""
conn = get_db()
if not conn:
return False
try:
cur = conn.cursor()
cur.execute("""
UPDATE stock_fundamental
SET roe = %s, eps = %s, bps = %s,
revenue_yoy = %s, profit_yoy = %s,
gross_margin = %s, net_margin = %s,
updated_at = NOW()
WHERE code = %s
""", (
data.get('roe'),
data.get('eps'),
data.get('bps'),
data.get('revenue_yoy'),
data.get('profit_yoy'),
data.get('gross_margin'),
data.get('net_margin'),
stock_code
))
conn.commit()
return True
except Exception as e:
conn.rollback()
print(f" 更新 {stock_code} 失败: {e}")
return False
finally:
conn.close()
def main():
print("=" * 50)
print("批量更新基本面财务指标")
print("=" * 50)
# 获取需要更新的股票
stocks = get_stocks_need_update()
print(f"\n需要更新的股票数量: {len(stocks)}")
if not stocks:
print("所有股票财务指标已完整,无需更新")
return
success_count = 0
fail_count = 0
for i, (code, name) in enumerate(stocks, 1):
print(f"\n[{i}/{len(stocks)}] 正在更新 {code} {name}...")
# 获取财务指标
data = fetch_financial_indicators(code)
if data:
# 更新数据库
if update_stock_fundamental(code, data):
print(f" ✓ 更新成功: EPS={data.get('eps')}, ROE={data.get('roe')}%")
success_count += 1
else:
fail_count += 1
else:
print(f" ✗ 无法获取财务指标")
fail_count += 1
# 避免请求过快
time.sleep(0.5)
print("\n" + "=" * 50)
print(f"更新完成! 成功: {success_count}, 失败: {fail_count}")
print("=" * 50)
if __name__ == '__main__':
main()