Files
etf/archive/single_files/fetch_159930.py
aszerW 1fca536c95 refactor: 归档旧代码,保留新框架结构
归档内容:
- core/ (数据源、因子计算、通用工具) → archive/legacy_core/
- strategies/rotation/engine.py, portfolio.py, report.py → archive/legacy_core/
- scripts/ (run_rotation, daily_scheduler) → archive/legacy_scripts/
- examples/ → archive/legacy_examples/
- tests/ (实验、对比测试) → archive/legacy_tests/
- 单独文件 (fetch_*.py, 动量.py, 全球市场.py等) → archive/single_files/

保留新结构:
- framework/ (抽象接口)
- strategies/shared/ (定制组件)
- strategies/rotation/strategy.py (新策略)
- 外层配置: .env, .dockerignore, build-and-push.sh, hk_ecs.pem, README.md, requirements.txt
- Docker相关: Dockerfile, Dockerfile_base, docker-compose.yml

更新README反映新框架架构
2026-05-11 23:34:23 +08:00

184 lines
5.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
获取159930 ETF最新10天的收盘价、净值并计算溢价率
"""
import os
import pandas as pd
import tushare as ts
from datetime import datetime, timedelta
# 设置Tushare token
def get_tushare_token():
# 首先尝试从环境变量获取
token = os.environ.get("TUSHARE_TOKEN")
if token:
return token
# 尝试从.env文件获取
try:
from dotenv import load_dotenv
load_dotenv()
token = os.environ.get("TUSHARE_TOKEN")
if token:
return token
except ImportError:
pass
# 手动读取.env文件
env_path = os.path.join(os.path.dirname(__file__), '.env')
if os.path.exists(env_path):
with open(env_path, 'r') as f:
for line in f:
if line.startswith('TUSHARE_TOKEN='):
token = line.strip().split('=', 1)[1].strip().strip('"').strip("'")
if token:
return token
raise ValueError("请设置 TUSHARE_TOKEN 环境变量或在.env文件中配置")
def fetch_etf_data(etf_code: str, days: int = 10):
"""
获取ETF最新N天的价格、净值数据
Args:
etf_code: ETF代码"159930.SZ"
days: 获取天数
Returns:
DataFrame: 包含日期、收盘价、净值、溢价率
"""
pro = ts.pro_api(get_tushare_token())
# 计算日期范围(多取几天确保有足够数据)
end_date = datetime.now()
start_date = end_date - timedelta(days=days + 5)
start_str = start_date.strftime('%Y%m%d')
end_str = end_date.strftime('%Y%m%d')
# 转换代码格式
ts_code = etf_code.replace(".SS", ".SH")
print(f"获取 {etf_code} 数据...")
print(f"日期范围: {start_str} ~ {end_str}")
# 1. 获取ETF价格数据fund_daily接口
print("\n1. 获取ETF价格数据...")
try:
price_df = pro.fund_daily(
ts_code=ts_code,
start_date=start_str,
end_date=end_str
)
if price_df is not None and len(price_df) > 0:
price_df = price_df.sort_values('trade_date')
print(f" 获取到 {len(price_df)} 条价格数据")
print(f" 最新日期: {price_df['trade_date'].max()}")
else:
print(" 未获取到价格数据")
price_df = None
except Exception as e:
print(f" 获取价格数据失败: {e}")
price_df = None
# 2. 获取ETF净值数据fund_nav接口
print("\n2. 获取ETF净值数据...")
try:
# 净值通常滞后,多取一天
nav_end_date = end_date + timedelta(days=1)
nav_end_str = nav_end_date.strftime('%Y%m%d')
nav_df = pro.fund_nav(
ts_code=ts_code,
start_date=start_str,
end_date=nav_end_str
)
if nav_df is not None and len(nav_df) > 0:
nav_df = nav_df.sort_values('nav_date')
print(f" 获取到 {len(nav_df)} 条净值数据")
print(f" 最新日期: {nav_df['nav_date'].max()}")
else:
print(" 未获取到净值数据")
nav_df = None
except Exception as e:
print(f" 获取净值数据失败: {e}")
nav_df = None
# 3. 合并数据并计算溢价率
print("\n3. 合并数据并计算溢价率...")
if price_df is None:
print("错误: 没有价格数据")
return None
# 准备价格数据
price_df['date'] = pd.to_datetime(price_df['trade_date'])
price_df = price_df.set_index('date')
price_series = price_df['close']
# 准备净值数据
if nav_df is not None:
nav_df['date'] = pd.to_datetime(nav_df['nav_date'])
nav_df = nav_df.set_index('date')
nav_series = nav_df['unit_nav']
else:
nav_series = pd.Series()
# 创建结果DataFrame
result = pd.DataFrame({
'收盘价': price_series
})
# 对齐净值数据(按日期)
result = result.join(nav_series.rename('净值'), how='left')
# 计算溢价率
result['溢价率'] = (result['收盘价'] - result['净值']) / result['净值'] * 100
# 取最新N天
result = result.tail(days)
# 格式化输出
result['收盘价'] = result['收盘价'].round(3)
result['净值'] = result['净值'].round(3)
result['溢价率'] = result['溢价率'].round(2)
# 重置索引,将日期作为列
result = result.reset_index()
result['日期'] = result['date'].dt.strftime('%Y-%m-%d')
result = result[['日期', '收盘价', '净值', '溢价率']]
return result
def main():
"""主函数"""
etf_code = "159930.SZ"
days = 10
print("=" * 60)
print(f"ETF: {etf_code} (中证能源ETF)")
print(f"获取最近 {days} 天数据")
print("=" * 60)
df = fetch_etf_data(etf_code, days)
if df is not None and len(df) > 0:
print("\n" + "=" * 60)
print("结果表格:")
print("=" * 60)
print(df.to_string(index=False))
# 保存到CSV
output_file = f"{etf_code.replace('.', '_')}_latest_{days}days.csv"
df.to_csv(output_file, index=False, encoding='utf-8-sig')
print(f"\n数据已保存到: {output_file}")
else:
print("\n获取数据失败")
if __name__ == "__main__":
main()