154 lines
4.5 KiB
Python
154 lines
4.5 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
获取股票价格和标普500指数(最终版)
|
||
"""
|
||
|
||
import requests
|
||
import json
|
||
from datetime import datetime
|
||
|
||
# Yahoo Finance API 配置
|
||
YAHOO_API_URL = "https://query1.finance.yahoo.com/v8/finance/chart/"
|
||
|
||
# 指数配置
|
||
INDEXES = {
|
||
"^GSPC": "标普500",
|
||
"^IXIC": "纳斯达克",
|
||
"^DJI": "道琼斯"
|
||
}
|
||
|
||
# 股票配置(从Notion数据库读取)
|
||
STOCKS = [
|
||
{"symbol": "MSFT", "name": "Microsoft Corporation", "quantity": 1, "cost_basis": 439.00}
|
||
]
|
||
|
||
def get_stock_price(symbol):
|
||
"""获取股票实时价格"""
|
||
|
||
try:
|
||
url = f"{YAHOO_API_URL}{symbol}"
|
||
params = {
|
||
"interval": "1d",
|
||
"range": "1d"
|
||
}
|
||
|
||
headers = {
|
||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
|
||
}
|
||
|
||
response = requests.get(url, params=params, headers=headers, timeout=10)
|
||
|
||
if response.status_code == 200:
|
||
data = response.json()
|
||
|
||
# 检查响应结构
|
||
if "chart" in data and "result" in data["chart"]:
|
||
result = data["chart"]["result"]
|
||
if result and len(result) > 0:
|
||
meta = result[0].get("meta", {})
|
||
current_price = meta.get("regularMarketPrice")
|
||
previous_close = meta.get("previousClose")
|
||
|
||
if current_price and previous_close:
|
||
change = current_price - previous_close
|
||
change_percent = (change / previous_close) * 100
|
||
|
||
return {
|
||
"symbol": symbol,
|
||
"price": current_price,
|
||
"previous_close": previous_close,
|
||
"change": change,
|
||
"change_percent": change_percent,
|
||
"currency": meta.get("currency", "USD")
|
||
}
|
||
|
||
return None
|
||
|
||
except Exception as e:
|
||
print(f"获取 {symbol} 价格失败: {e}")
|
||
return None
|
||
|
||
def get_index_prices():
|
||
"""获取指数价格"""
|
||
|
||
print("=" * 60)
|
||
print("获取指数价格")
|
||
print("=" * 60)
|
||
|
||
indexes = {}
|
||
|
||
for symbol, name in INDEXES.items():
|
||
price_data = get_stock_price(symbol)
|
||
if price_data:
|
||
indexes[symbol] = {
|
||
"name": name,
|
||
"price": price_data["price"],
|
||
"change": price_data["change"],
|
||
"change_percent": price_data["change_percent"]
|
||
}
|
||
print(f"{name}: {price_data['price']:.2f} ({price_data['change_percent']:+.2f}%)")
|
||
else:
|
||
print(f"{name}: 获取失败")
|
||
|
||
print("=" * 60)
|
||
return indexes
|
||
|
||
def get_stock_prices():
|
||
"""获取持仓股票价格"""
|
||
|
||
print("=" * 60)
|
||
print("获取持仓股票价格")
|
||
print("=" * 60)
|
||
|
||
stock_prices = {}
|
||
|
||
for stock in STOCKS:
|
||
symbol = stock["symbol"]
|
||
price_data = get_stock_price(symbol)
|
||
if price_data:
|
||
stock_prices[symbol] = {
|
||
"name": stock["name"],
|
||
"quantity": stock["quantity"],
|
||
"cost_basis": stock["cost_basis"],
|
||
"current_price": price_data["price"],
|
||
"change": price_data["change"],
|
||
"change_percent": price_data["change_percent"]
|
||
}
|
||
print(f"{symbol}: ${price_data['price']:.2f} ({price_data['change_percent']:+.2f}%)")
|
||
else:
|
||
print(f"{symbol}: 获取失败")
|
||
|
||
print("=" * 60)
|
||
return stock_prices
|
||
|
||
def main():
|
||
"""主函数"""
|
||
print("开始获取股票价格和指数...")
|
||
print()
|
||
|
||
# 获取指数价格
|
||
indexes = get_index_prices()
|
||
|
||
# 获取持仓股票价格
|
||
stock_prices = get_stock_prices()
|
||
|
||
# 打印汇总
|
||
print("\n📊 数据汇总:")
|
||
print("=" * 60)
|
||
|
||
if indexes:
|
||
print(f"\n指数数据: {len(indexes)} 个")
|
||
for symbol, data in indexes.items():
|
||
print(f" {data['name']}: {data['price']:.2f} ({data['change_percent']:+.2f}%)")
|
||
|
||
if stock_prices:
|
||
print(f"\n持仓股票: {len(stock_prices)} 个")
|
||
for symbol, data in stock_prices.items():
|
||
print(f" {data['name']}: ${data['current_price']:.2f} ({data['change_percent']:+.2f}%)")
|
||
|
||
print("=" * 60)
|
||
|
||
if __name__ == "__main__":
|
||
main()
|