mirror of
https://github.com/shiyu-coder/Kronos.git
synced 2026-05-06 22:13:39 +08:00
661 lines
24 KiB
Python
661 lines
24 KiB
Python
import pandas as pd
|
||
import requests
|
||
import json
|
||
from datetime import datetime, timedelta
|
||
import os
|
||
import time
|
||
import random
|
||
|
||
|
||
def get_stock_market(stock_code):
|
||
"""
|
||
根据股票代码判断市场类型
|
||
返回: 市场前缀 '0'-深交所, '1'-上交所
|
||
"""
|
||
if stock_code.startswith(('0', '2', '3')):
|
||
return '0' # 深交所
|
||
elif stock_code.startswith(('6', '9')):
|
||
return '1' # 上交所
|
||
else:
|
||
return '1' # 默认上交所
|
||
|
||
|
||
def get_stock_data_eastmoney_all_history(stock_code="002354"):
|
||
"""
|
||
使用东方财富网API获取股票所有历史数据
|
||
"""
|
||
try:
|
||
print(f"正在从东方财富网获取股票 {stock_code} 的全部历史数据...")
|
||
|
||
# 获取市场类型
|
||
market = get_stock_market(stock_code)
|
||
secid = f"{market}.{stock_code}"
|
||
|
||
# 使用东方财富API获取所有历史数据
|
||
url = "http://push2his.eastmoney.com/api/qt/stock/kline/get"
|
||
|
||
# 设置足够早的起始日期(中国股市从1990年开始)
|
||
start_date = "19900101"
|
||
end_date = datetime.now().strftime('%Y%m%d')
|
||
|
||
params = {
|
||
'secid': secid,
|
||
'fields1': 'f1,f2,f3,f4,f5,f6',
|
||
'fields2': 'f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61',
|
||
'klt': '101', # 日线
|
||
'fqt': '1', # 前复权
|
||
'beg': start_date,
|
||
'end': end_date,
|
||
'lmt': '50000', # 增加限制数量以获取更多历史数据
|
||
'ut': 'fa5fd1943c7b386f172d6893dbfba10b',
|
||
'cb': f'jQuery{random.randint(1000000, 9999999)}_{int(time.time() * 1000)}'
|
||
}
|
||
|
||
headers = {
|
||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36',
|
||
'Referer': 'https://quote.eastmoney.com/',
|
||
'Accept': '*/*',
|
||
}
|
||
|
||
time.sleep(random.uniform(1, 2))
|
||
|
||
response = requests.get(url, params=params, headers=headers, timeout=15)
|
||
|
||
print(f"API响应状态码: {response.status_code}")
|
||
|
||
if response.status_code == 200:
|
||
# 处理JSONP响应
|
||
response_text = response.text
|
||
|
||
# 提取JSON数据(处理JSONP格式)
|
||
if response_text.startswith('/**/'):
|
||
response_text = response_text[4:]
|
||
|
||
# 查找JSON数据的开始和结束位置
|
||
start_idx = response_text.find('(')
|
||
end_idx = response_text.rfind(')')
|
||
|
||
if start_idx != -1 and end_idx != -1:
|
||
json_str = response_text[start_idx + 1:end_idx]
|
||
try:
|
||
data = json.loads(json_str)
|
||
except json.JSONDecodeError:
|
||
print("❌ JSON解析失败,尝试直接解析...")
|
||
return parse_kline_data_directly_all_history(response_text, stock_code)
|
||
else:
|
||
print("❌ 无法找到JSON数据边界")
|
||
return None
|
||
|
||
print(f"API返回数据状态: {data.get('rc', 'N/A')}")
|
||
|
||
if data and data.get('data') is not None:
|
||
klines = data['data'].get('klines', [])
|
||
print(f"获取到 {len(klines)} 条历史K线数据")
|
||
|
||
if not klines:
|
||
print("⚠️ K线数据为空")
|
||
return None
|
||
|
||
# 解析数据
|
||
stock_data = []
|
||
for kline in klines:
|
||
try:
|
||
items = kline.split(',')
|
||
if len(items) >= 6:
|
||
stock_data.append({
|
||
'日期': items[0],
|
||
'股票代码': stock_code,
|
||
'开盘价': float(items[1]),
|
||
'收盘价': float(items[2]),
|
||
'最高价': float(items[3]),
|
||
'最低价': float(items[4]),
|
||
'成交量': float(items[5]),
|
||
'成交额': float(items[6]) if len(items) > 6 else 0,
|
||
'振幅': float(items[7]) if len(items) > 7 else 0,
|
||
'涨跌幅': float(items[8]) if len(items) > 8 else 0,
|
||
'涨跌额': float(items[9]) if len(items) > 9 else 0,
|
||
'换手率': float(items[10]) if len(items) > 10 else 0
|
||
})
|
||
except (ValueError, IndexError) as e:
|
||
continue
|
||
|
||
if not stock_data:
|
||
print("❌ 解析后无有效数据")
|
||
return None
|
||
|
||
df = pd.DataFrame(stock_data)
|
||
df['日期'] = pd.to_datetime(df['日期'])
|
||
df.set_index('日期', inplace=True)
|
||
df = df.sort_index()
|
||
|
||
print(f"✅ 成功获取 {len(df)} 条历史数据")
|
||
print(
|
||
f"历史数据时间范围: {df.index.min().strftime('%Y-%m-%d')} 到 {df.index.max().strftime('%Y-%m-%d')}")
|
||
return df
|
||
else:
|
||
print("❌ API返回数据为空")
|
||
return None
|
||
else:
|
||
print(f"❌ 请求失败,状态码: {response.status_code}")
|
||
return None
|
||
|
||
except Exception as e:
|
||
print(f"❌ 获取历史数据时出错: {str(e)}")
|
||
return None
|
||
|
||
|
||
def parse_kline_data_directly_all_history(response_text, stock_code):
|
||
"""
|
||
直接解析K线数据(当JSON解析失败时使用)- 全历史版本
|
||
"""
|
||
try:
|
||
# 尝试直接从响应文本中提取K线数据
|
||
if '"klines":[' in response_text:
|
||
start_idx = response_text.find('"klines":[') + 10
|
||
end_idx = response_text.find(']', start_idx)
|
||
klines_str = response_text[start_idx:end_idx]
|
||
|
||
# 清理字符串并分割
|
||
klines = [k.strip().strip('"') for k in klines_str.split('","') if k.strip()]
|
||
|
||
stock_data = []
|
||
for kline in klines:
|
||
if kline.strip():
|
||
items = kline.split(',')
|
||
if len(items) >= 6:
|
||
stock_data.append({
|
||
'日期': items[0],
|
||
'股票代码': stock_code,
|
||
'开盘价': float(items[1]),
|
||
'收盘价': float(items[2]),
|
||
'最高价': float(items[3]),
|
||
'最低价': float(items[4]),
|
||
'成交量': float(items[5]),
|
||
'成交额': float(items[6]) if len(items) > 6 else 0,
|
||
})
|
||
|
||
if stock_data:
|
||
df = pd.DataFrame(stock_data)
|
||
df['日期'] = pd.to_datetime(df['日期'])
|
||
df.set_index('日期', inplace=True)
|
||
df = df.sort_index()
|
||
print(f"✅ 直接解析获取 {len(df)} 条历史数据")
|
||
return df
|
||
except Exception as e:
|
||
print(f"❌ 直接解析也失败: {e}")
|
||
|
||
return None
|
||
|
||
|
||
def get_stock_data_akshare_all_history(stock_code="002354"):
|
||
"""
|
||
使用AKShare作为备用数据源 - 全历史版本
|
||
"""
|
||
try:
|
||
print(f"尝试使用AKShare获取股票 {stock_code} 全部历史数据...")
|
||
import akshare as ak
|
||
|
||
# 获取所有历史数据
|
||
df = ak.stock_zh_a_hist(symbol=stock_code, period="daily",
|
||
adjust="qfq")
|
||
|
||
if df is not None and not df.empty:
|
||
# 重命名列以匹配我们的格式
|
||
column_mapping = {
|
||
'日期': '日期',
|
||
'开盘': '开盘价',
|
||
'收盘': '收盘价',
|
||
'最高': '最高价',
|
||
'最低': '最低价',
|
||
'成交量': '成交量',
|
||
'成交额': '成交额',
|
||
'振幅': '振幅',
|
||
'涨跌幅': '涨跌幅',
|
||
'涨跌额': '涨跌额',
|
||
'换手率': '换手率'
|
||
}
|
||
|
||
# 只映射存在的列
|
||
actual_mapping = {k: v for k, v in column_mapping.items() if k in df.columns}
|
||
df = df.rename(columns=actual_mapping)
|
||
|
||
# 添加股票代码列
|
||
df['股票代码'] = stock_code
|
||
df['日期'] = pd.to_datetime(df['日期'])
|
||
df.set_index('日期', inplace=True)
|
||
df = df.sort_index()
|
||
|
||
print(f"✅ AKShare成功获取 {len(df)} 条历史数据")
|
||
print(f"时间范围: {df.index.min().strftime('%Y-%m-%d')} 到 {df.index.max().strftime('%Y-%m-%d')}")
|
||
return df
|
||
else:
|
||
print("❌ AKShare未返回数据")
|
||
return None
|
||
|
||
except ImportError:
|
||
print("⚠️ AKShare未安装,使用 pip install akshare 安装")
|
||
return None
|
||
except Exception as e:
|
||
print(f"❌ AKShare获取历史数据失败: {e}")
|
||
return None
|
||
|
||
|
||
def get_stock_data_baostock_all_history(stock_code="002354"):
|
||
"""
|
||
使用Baostock作为第三个数据源 - 全历史版本
|
||
"""
|
||
try:
|
||
print(f"尝试使用Baostock获取股票 {stock_code} 全部历史数据...")
|
||
import baostock as bs
|
||
import pandas as pd
|
||
|
||
# 登录系统
|
||
lg = bs.login()
|
||
|
||
# 根据市场添加前缀
|
||
market = get_stock_market(stock_code)
|
||
if market == '0':
|
||
full_code = f"sz.{stock_code}"
|
||
else:
|
||
full_code = f"sh.{stock_code}"
|
||
|
||
# 获取上市日期
|
||
rs = bs.query_stock_basic(code=full_code)
|
||
if rs.error_code != '0':
|
||
print(f"❌ 获取股票基本信息失败: {rs.error_msg}")
|
||
bs.logout()
|
||
return None
|
||
|
||
# 获取上市日期
|
||
list_date = None
|
||
while (rs.error_code == '0') & rs.next():
|
||
list_date = rs.get_row_data()[2] # 上市日期在第三个字段
|
||
|
||
if not list_date:
|
||
print("❌ 无法获取上市日期")
|
||
bs.logout()
|
||
return None
|
||
|
||
print(f"股票上市日期: {list_date}")
|
||
|
||
# 获取从上市日期到现在的所有数据
|
||
end_date = datetime.now().strftime('%Y-%m-%d')
|
||
|
||
# 获取数据
|
||
rs = bs.query_history_k_data_plus(
|
||
full_code,
|
||
"date,open,high,low,close,volume,amount,turn,pctChg",
|
||
start_date=list_date,
|
||
end_date=end_date,
|
||
frequency="d",
|
||
adjustflag="2" # 前复权
|
||
)
|
||
|
||
data_list = []
|
||
while (rs.error_code == '0') & rs.next():
|
||
data_list.append(rs.get_row_data())
|
||
|
||
# 退出系统
|
||
bs.logout()
|
||
|
||
if data_list:
|
||
df = pd.DataFrame(data_list, columns=rs.fields)
|
||
|
||
# 数据类型转换
|
||
df['date'] = pd.to_datetime(df['date'])
|
||
df['open'] = pd.to_numeric(df['open'], errors='coerce')
|
||
df['high'] = pd.to_numeric(df['high'], errors='coerce')
|
||
df['low'] = pd.to_numeric(df['low'], errors='coerce')
|
||
df['close'] = pd.to_numeric(df['close'], errors='coerce')
|
||
df['volume'] = pd.to_numeric(df['volume'], errors='coerce')
|
||
df['amount'] = pd.to_numeric(df['amount'], errors='coerce')
|
||
df['turn'] = pd.to_numeric(df['turn'], errors='coerce')
|
||
df['pctChg'] = pd.to_numeric(df['pctChg'], errors='coerce')
|
||
|
||
# 重命名列
|
||
df = df.rename(columns={
|
||
'date': '日期',
|
||
'open': '开盘价',
|
||
'high': '最高价',
|
||
'low': '最低价',
|
||
'close': '收盘价',
|
||
'volume': '成交量',
|
||
'amount': '成交额',
|
||
'turn': '换手率',
|
||
'pctChg': '涨跌幅'
|
||
})
|
||
|
||
# 添加股票代码列
|
||
df['股票代码'] = stock_code
|
||
df.set_index('日期', inplace=True)
|
||
df = df.sort_index()
|
||
|
||
# 计算涨跌额
|
||
df['涨跌额'] = df['收盘价'].diff()
|
||
|
||
# 清理无效数据
|
||
df = df.dropna()
|
||
|
||
print(f"✅ Baostock成功获取 {len(df)} 条历史数据")
|
||
print(f"时间范围: {df.index.min().strftime('%Y-%m-%d')} 到 {df.index.max().strftime('%Y-%m-%d')}")
|
||
return df
|
||
else:
|
||
print("❌ Baostock未返回数据")
|
||
return None
|
||
|
||
except ImportError:
|
||
print("⚠️ Baostock未安装,使用 pip install baostock 安装")
|
||
return None
|
||
except Exception as e:
|
||
print(f"❌ Baostock获取历史数据失败: {e}")
|
||
return None
|
||
|
||
|
||
def get_stock_data_with_retry_all_history(stock_code="002354", retry_count=2):
|
||
"""
|
||
带重试机制的数据获取 - 多数据源全历史版本
|
||
"""
|
||
data_sources = [
|
||
("AKShare", get_stock_data_akshare_all_history),
|
||
("Baostock", get_stock_data_baostock_all_history),
|
||
("东方财富", get_stock_data_eastmoney_all_history)
|
||
]
|
||
|
||
for source_name, data_func in data_sources:
|
||
print(f"\n🔍 尝试从 {source_name} 获取全部历史数据...")
|
||
data = data_func(stock_code)
|
||
|
||
if data is not None and not data.empty:
|
||
print(f"✅ {source_name} 历史数据获取成功!")
|
||
# 标记数据来源
|
||
data.attrs['data_source'] = source_name
|
||
return data
|
||
|
||
print("❌ 所有真实数据源都失败,使用示例数据...")
|
||
return create_sample_data_all_history(stock_code)
|
||
|
||
|
||
def create_sample_data_all_history(stock_code="002354"):
|
||
"""
|
||
创建更真实的历史示例数据 - 从上市年份开始
|
||
"""
|
||
# 模拟不同股票的上市年份
|
||
list_years = {
|
||
'600580': 2002, # 卧龙电驱
|
||
'002354': 2010, # 天娱数科
|
||
'300418': 2015, # 昆仑万维
|
||
'300207': 2011, # 欣旺达
|
||
}
|
||
|
||
list_year = list_years.get(stock_code, 2010)
|
||
current_year = datetime.now().year
|
||
|
||
print(f"📊 创建 {stock_code} 从 {list_year} 年上市至今的示例数据...")
|
||
|
||
# 生成从上市年份到现在的交易日(排除周末)
|
||
start_date = datetime(list_year, 1, 1)
|
||
end_date = datetime.now()
|
||
all_dates = pd.bdate_range(start=start_date, end=end_date, freq='B')
|
||
|
||
# 生成更真实的股价数据
|
||
import numpy as np
|
||
np.random.seed(42)
|
||
|
||
# 设置合理的基准价格(根据股票类型)
|
||
base_prices = {
|
||
'600580': 8.0, # 卧龙电驱
|
||
'002354': 15.0, # 天娱数科 - 上市时价格较高
|
||
'300418': 20.0, # 昆仑万维
|
||
'300207': 12.0, # 欣旺达
|
||
}
|
||
base_price = base_prices.get(stock_code, 10.0)
|
||
|
||
stock_data = []
|
||
current_price = base_price
|
||
|
||
for i, date in enumerate(all_dates):
|
||
# 模拟真实的市场波动
|
||
volatility = 0.02 # 2%的日波动率
|
||
|
||
if i > 0:
|
||
# 使用随机游走模拟价格变化
|
||
daily_return = np.random.normal(0, volatility)
|
||
|
||
# 模拟不同年份的市场趋势
|
||
year = date.year
|
||
if year <= list_year + 2: # 上市初期波动较大
|
||
daily_return += np.random.normal(0.001, 0.01)
|
||
elif year <= list_year + 5: # 成长期
|
||
daily_return += np.random.normal(0.0005, 0.005)
|
||
else: # 成熟期
|
||
daily_return += np.random.normal(0.0002, 0.003)
|
||
|
||
current_price = current_price * (1 + daily_return)
|
||
|
||
# 价格边界限制
|
||
current_price = max(base_price * 0.3, min(base_price * 10.0, current_price))
|
||
else:
|
||
current_price = base_price
|
||
|
||
# 生成OHLC数据
|
||
open_variation = np.random.normal(0, volatility * 0.2)
|
||
open_price = current_price * (1 + open_variation)
|
||
|
||
daily_range = abs(np.random.normal(volatility * 0.8, volatility * 0.3))
|
||
high_price = max(open_price, current_price) * (1 + daily_range)
|
||
low_price = min(open_price, current_price) * (1 - daily_range)
|
||
close_price = current_price
|
||
|
||
# 确保价格合理性
|
||
high_price = max(open_price, close_price, low_price, high_price)
|
||
low_price = min(open_price, close_price, high_price, low_price)
|
||
|
||
# 生成成交量(随年份增长)
|
||
base_volume = 100000 + (year - list_year) * 50000 # 成交量逐年增长
|
||
volume_variation = abs(daily_return) * 5000000 if i > 0 else 0
|
||
volume = int(base_volume + volume_variation + np.random.randint(-200000, 400000))
|
||
volume = max(50000, volume)
|
||
|
||
# 计算成交额(万元)
|
||
amount = volume * close_price / 10000
|
||
|
||
# 计算涨跌幅和涨跌额
|
||
if i > 0:
|
||
prev_close = stock_data[-1]['收盘价']
|
||
price_change = close_price - prev_close
|
||
pct_change = (price_change / prev_close) * 100
|
||
else:
|
||
price_change = 0
|
||
pct_change = 0
|
||
|
||
# 计算振幅
|
||
amplitude = ((high_price - low_price) / open_price) * 100
|
||
|
||
# 生成换手率(1%-15%之间)
|
||
turnover_rate = np.random.uniform(1.0, 15.0)
|
||
|
||
stock_data.append({
|
||
'日期': date,
|
||
'股票代码': stock_code,
|
||
'开盘价': round(open_price, 2),
|
||
'收盘价': round(close_price, 2),
|
||
'最高价': round(high_price, 2),
|
||
'最低价': round(low_price, 2),
|
||
'成交量': volume,
|
||
'成交额': round(amount, 2),
|
||
'振幅': round(amplitude, 2),
|
||
'涨跌幅': round(pct_change, 2),
|
||
'涨跌额': round(price_change, 2),
|
||
'换手率': round(turnover_rate, 2)
|
||
})
|
||
|
||
df = pd.DataFrame(stock_data)
|
||
df.set_index('日期', inplace=True)
|
||
|
||
print(f"✅ 已创建 {len(df)} 条从 {list_year} 年至今的模拟历史数据")
|
||
print(f"时间范围: {df.index.min().strftime('%Y-%m-%d')} 到 {df.index.max().strftime('%Y-%m-%d')}")
|
||
|
||
# 标记为模拟数据
|
||
df.attrs['data_source'] = '模拟历史数据'
|
||
|
||
return df
|
||
|
||
|
||
def display_all_history_data_info(df, stock_code):
|
||
"""显示全历史数据信息"""
|
||
if df is None or df.empty:
|
||
print("没有数据可显示")
|
||
return
|
||
|
||
# 获取数据来源
|
||
data_source = df.attrs.get('data_source', '未知来源')
|
||
|
||
print(f"\n{'=' * 60}")
|
||
print(f"股票 {stock_code} 全部历史数据摘要")
|
||
print(f"{'=' * 60}")
|
||
|
||
print(f"数据时间范围: {df.index.min().strftime('%Y-%m-%d')} 到 {df.index.max().strftime('%Y-%m-%d')}")
|
||
print(f"总交易天数: {len(df):,}")
|
||
print(f"数据来源: {data_source}")
|
||
|
||
# 按年份显示统计
|
||
years = sorted(df.index.year.unique())
|
||
print(f"\n历史年份: {years}")
|
||
|
||
# 显示关键年份统计
|
||
key_years = [years[0]] # 上市年份
|
||
if len(years) > 1:
|
||
key_years.append(years[-1]) # 最新年份
|
||
if len(years) > 5:
|
||
key_years.extend([years[len(years) // 2], years[len(years) // 4], years[3 * len(years) // 4]])
|
||
|
||
for year in sorted(set(key_years)):
|
||
year_data = df[df.index.year == year]
|
||
if len(year_data) > 0:
|
||
print(f"\n{year}年统计:")
|
||
print(f" 交易天数: {len(year_data)}")
|
||
print(f" 平均收盘价: {year_data['收盘价'].mean():.2f} 元")
|
||
print(f" 最高价: {year_data['最高价'].max():.2f} 元")
|
||
print(f" 最低价: {year_data['最低价'].min():.2f} 元")
|
||
if len(year_data) > 1:
|
||
year_return = (year_data['收盘价'].iloc[-1] / year_data['收盘价'].iloc[0] - 1) * 100
|
||
print(f" 年度涨跌幅: {year_return:+.2f}%")
|
||
|
||
# 显示整体统计
|
||
print(f"\n整体统计:")
|
||
total_return = (df['收盘价'].iloc[-1] / df['收盘价'].iloc[0] - 1) * 100
|
||
print(f" 总涨跌幅: {total_return:+.2f}%")
|
||
print(f" 历史最高价: {df['最高价'].max():.2f} 元")
|
||
print(f" 历史最低价: {df['最低价'].min():.2f} 元")
|
||
print(f" 平均日成交量: {df['成交量'].mean():,.0f} 股")
|
||
|
||
# 显示最新交易日数据
|
||
latest_date = df.index.max()
|
||
print(f"\n最新交易日 ({latest_date.strftime('%Y-%m-%d')}) 数据:")
|
||
latest_data = df.loc[latest_date]
|
||
for col, value in latest_data.items():
|
||
if col != '股票代码':
|
||
if col in ['成交量']:
|
||
print(f" {col}: {value:,.0f}")
|
||
elif col in ['成交额']:
|
||
print(f" {col}: {value:,.2f} 万元")
|
||
else:
|
||
print(f" {col}: {value}")
|
||
|
||
|
||
def save_all_history_stock_data(df, stock_code, save_dir="D:/lianghuajiaoyi/Kronos/examples/data"):
|
||
"""
|
||
保存全历史股票数据到指定目录
|
||
"""
|
||
if df is not None and not df.empty:
|
||
# 确保保存目录存在
|
||
os.makedirs(save_dir, exist_ok=True)
|
||
|
||
# 保存CSV文件 - 使用全历史命名
|
||
csv_file = os.path.join(save_dir, f"{stock_code}_all_history.csv")
|
||
|
||
# 重置索引以便保存日期列
|
||
df_reset = df.reset_index()
|
||
df_reset.to_csv(csv_file, encoding='utf-8-sig', index=False)
|
||
|
||
print(f"\n📁 全历史股票数据已保存: {csv_file}")
|
||
|
||
# 同时保存一个按年份分割的版本
|
||
years = df_reset['日期'].dt.year.unique()
|
||
for year in years:
|
||
year_data = df_reset[df_reset['日期'].dt.year == year]
|
||
year_file = os.path.join(save_dir, f"{stock_code}_{year}.csv")
|
||
year_data.to_csv(year_file, encoding='utf-8-sig', index=False)
|
||
|
||
print(f"📁 同时保存了 {len(years)} 个年份的单独数据文件")
|
||
return True
|
||
return False
|
||
|
||
|
||
def main_all_history(stock_code="002354"):
|
||
"""
|
||
主函数:获取并保存股票全历史数据
|
||
"""
|
||
# 设置保存目录
|
||
save_directory = "D:/lianghuajiaoyi/Kronos/examples/data"
|
||
|
||
print("=" * 60)
|
||
print(f"开始获取股票 {stock_code} 的全部历史数据")
|
||
print("=" * 60)
|
||
print(f"数据将保存到: {save_directory}")
|
||
|
||
# 检查必要库
|
||
try:
|
||
import requests
|
||
import numpy as np
|
||
except ImportError:
|
||
print("正在安装必要库...")
|
||
import subprocess
|
||
subprocess.check_call(["pip", "install", "requests", "numpy", "pandas"])
|
||
import requests
|
||
import numpy as np
|
||
|
||
# 获取全历史数据(多数据源)
|
||
stock_data = get_stock_data_with_retry_all_history(stock_code)
|
||
|
||
if stock_data is not None:
|
||
# 显示数据信息
|
||
display_all_history_data_info(stock_data, stock_code)
|
||
|
||
# 保存全历史数据到指定目录
|
||
save_all_history_stock_data(stock_data, stock_code, save_directory)
|
||
|
||
print(f"\n🎉 股票 {stock_code} 全历史数据处理完成!")
|
||
print(
|
||
f"数据时间跨度: {stock_data.index.min().strftime('%Y-%m-%d')} 到 {stock_data.index.max().strftime('%Y-%m-%d')}")
|
||
print(f"总交易天数: {len(stock_data):,}")
|
||
|
||
# 显示保存的文件
|
||
csv_file = os.path.join(save_directory, f"{stock_code}_all_history.csv")
|
||
if os.path.exists(csv_file):
|
||
file_size = os.path.getsize(csv_file) / 1024 # KB
|
||
print(f"📄 生成的文件: {csv_file} ({file_size:.1f} KB)")
|
||
else:
|
||
print("❌ 未能获取股票全历史数据")
|
||
|
||
|
||
# 使用方法说明
|
||
if __name__ == "__main__":
|
||
"""
|
||
使用方法:
|
||
修改下面的参数来获取不同股票的全历史数据
|
||
"""
|
||
|
||
# ==================== 在这里修改参数 ====================
|
||
TARGET_STOCK_CODE = "300418" # 股票代码
|
||
# =====================================================
|
||
|
||
print("股票全历史数据获取工具")
|
||
print("说明:修改代码中的 TARGET_STOCK_CODE 来获取不同股票的全部历史数据")
|
||
print(f"当前设置: 股票代码={TARGET_STOCK_CODE}")
|
||
print()
|
||
|
||
# 运行主程序
|
||
main_all_history(stock_code=TARGET_STOCK_CODE)
|
||
|
||
print(f"\n💡 提示:要获取其他股票的全历史数据,请修改代码中的 TARGET_STOCK_CODE 变量") |