from flask import Blueprint, request, jsonify import pandas as pd import json from datetime import datetime bp = Blueprint('limitanalyse', __name__, url_prefix='/api/limit-analyse') @bp.route('/available-dates', methods=['GET']) def get_available_dates(): """获取可用日期列表""" try: # 模拟可用日期 dates = [ '2025-07-16', '2025-07-15', '2025-07-14', '2025-07-11', '2025-07-10' ] return jsonify({ 'success': True, 'data': dates }) except Exception as e: print(f"Error getting available dates: {e}") return jsonify({'success': False, 'error': str(e)}), 500 def load_stock_data(datestr): """加载股票数据""" try: # 模拟股票数据 data = [] for i in range(100): data.append({ 'code': f'00000{i:03d}', 'name': f'股票{i}', 'price': 10.0 + i * 0.1, 'change': (i % 10 - 5) * 0.5, 'sector': f'板块{i % 5}', 'limit_type': '涨停' if i % 10 == 0 else '正常', 'volume': 1000000 + i * 50000, 'amount': 10000000 + i * 500000 }) return pd.DataFrame(data) except Exception as e: print(f"Error loading stock data: {e}") return pd.DataFrame() @bp.route('/data', methods=['GET']) def get_analysis_data(): """获取分析数据""" try: date = request.args.get('date', '2025-07-16') # 加载数据 df = load_stock_data(date) if df.empty: return jsonify({'success': False, 'error': '数据加载失败'}), 500 # 统计信息 total_stocks = len(df) limit_up_stocks = len(df[df['limit_type'] == '涨停']) limit_down_stocks = len(df[df['limit_type'] == '跌停']) # 板块统计 sector_stats = df.groupby('sector').agg({ 'code': 'count', 'change': 'mean', 'volume': 'sum' }).reset_index() sector_data = [] for _, row in sector_stats.iterrows(): sector_data.append({ 'sector': row['sector'], 'stock_count': int(row['code']), 'avg_change': round(row['change'], 2), 'total_volume': int(row['volume']) }) return jsonify({ 'success': True, 'data': { 'date': date, 'total_stocks': total_stocks, 'limit_up_stocks': limit_up_stocks, 'limit_down_stocks': limit_down_stocks, 'sector_stats': sector_data } }) except Exception as e: print(f"Error getting analysis data: {e}") return jsonify({'success': False, 'error': str(e)}), 500 @bp.route('/sector-data', methods=['GET']) def get_sector_data(): """获取板块数据""" try: date = request.args.get('date', '2025-07-16') # 加载数据 df = load_stock_data(date) if df.empty: return jsonify({'success': False, 'error': '数据加载失败'}), 500 # 板块统计 sector_stats = df.groupby('sector').agg({ 'code': 'count', 'change': 'mean', 'volume': 'sum', 'amount': 'sum' }).reset_index() sector_data = [] for _, row in sector_stats.iterrows(): sector_data.append({ 'sector': row['sector'], 'stock_count': int(row['code']), 'avg_change': round(row['change'], 2), 'total_volume': int(row['volume']), 'total_amount': int(row['amount']) }) return jsonify({ 'success': True, 'data': sector_data }) except Exception as e: print(f"Error getting sector data: {e}") return jsonify({'success': False, 'error': str(e)}), 500 @bp.route('/word-cloud', methods=['GET']) def get_word_cloud_data(): """获取词云数据""" try: date = request.args.get('date', '2025-07-16') # 模拟词云数据 word_data = [ {'word': '科技', 'value': 100}, {'word': '新能源', 'value': 85}, {'word': '医药', 'value': 70}, {'word': '消费', 'value': 65}, {'word': '金融', 'value': 50}, {'word': '地产', 'value': 45}, {'word': '制造', 'value': 40}, {'word': '农业', 'value': 35}, {'word': '传媒', 'value': 30}, {'word': '环保', 'value': 25} ] return jsonify({ 'success': True, 'data': word_data }) except Exception as e: print(f"Error getting word cloud data: {e}") return jsonify({'success': False, 'error': str(e)}), 500 @bp.route('/chart-data', methods=['GET']) def get_chart_data(): """获取图表数据""" try: date = request.args.get('date', '2025-07-16') # 模拟图表数据 chart_data = { 'limit_up_distribution': [ {'sector': '科技', 'count': 15}, {'sector': '新能源', 'count': 12}, {'sector': '医药', 'count': 10}, {'sector': '消费', 'count': 8}, {'sector': '金融', 'count': 6} ], 'sector_performance': [ {'sector': '科技', 'change': 2.5}, {'sector': '新能源', 'change': 1.8}, {'sector': '医药', 'change': 1.2}, {'sector': '消费', 'change': 0.8}, {'sector': '金融', 'change': 0.5} ] } return jsonify({ 'success': True, 'data': chart_data }) except Exception as e: print(f"Error getting chart data: {e}") return jsonify({'success': False, 'error': str(e)}), 500 @bp.route('/stock-details', methods=['GET']) def get_stock_details(): """获取股票详情""" try: code = request.args.get('code') date = request.args.get('date', '2025-07-16') if not code: return jsonify({'success': False, 'error': '请提供股票代码'}), 400 # 模拟股票详情 stock_detail = { 'code': code, 'name': f'股票{code}', 'price': 15.50, 'change': 2.5, 'sector': '科技', 'volume': 1500000, 'amount': 23250000, 'limit_type': '涨停', 'turnover_rate': 3.2, 'market_cap': 15500000000 } return jsonify({ 'success': True, 'data': stock_detail }) except Exception as e: print(f"Error getting stock details: {e}") return jsonify({'success': False, 'error': str(e)}), 500 @bp.route('/sector-analysis', methods=['GET']) def get_sector_analysis(): """获取板块分析""" try: sector = request.args.get('sector') date = request.args.get('date', '2025-07-16') if not sector: return jsonify({'success': False, 'error': '请提供板块名称'}), 400 # 模拟板块分析数据 sector_analysis = { 'sector': sector, 'stock_count': 25, 'avg_change': 1.8, 'limit_up_count': 8, 'limit_down_count': 2, 'total_volume': 50000000, 'total_amount': 750000000, 'top_stocks': [ {'code': '000001', 'name': '股票A', 'change': 10.0}, {'code': '000002', 'name': '股票B', 'change': 9.5}, {'code': '000003', 'name': '股票C', 'change': 8.8} ] } return jsonify({ 'success': True, 'data': sector_analysis }) except Exception as e: print(f"Error getting sector analysis: {e}") return jsonify({'success': False, 'error': str(e)}), 500 @bp.route('/trend-analysis', methods=['GET']) def get_trend_analysis(): """获取趋势分析""" try: date = request.args.get('date', '2025-07-16') # 模拟趋势分析数据 trend_data = { 'limit_up_trend': [ {'date': '2025-07-10', 'count': 45}, {'date': '2025-07-11', 'count': 52}, {'date': '2025-07-14', 'count': 48}, {'date': '2025-07-15', 'count': 55}, {'date': '2025-07-16', 'count': 51} ], 'sector_trend': [ {'sector': '科技', 'trend': 'up'}, {'sector': '新能源', 'trend': 'up'}, {'sector': '医药', 'trend': 'stable'}, {'sector': '消费', 'trend': 'down'}, {'sector': '金融', 'trend': 'stable'} ] } return jsonify({ 'success': True, 'data': trend_data }) except Exception as e: print(f"Error getting trend analysis: {e}") return jsonify({'success': False, 'error': str(e)}), 500 @bp.route('/heat-map', methods=['GET']) def get_heat_map_data(): """获取热力图数据""" try: date = request.args.get('date', '2025-07-16') # 模拟热力图数据 heat_map_data = [] sectors = ['科技', '新能源', '医药', '消费', '金融', '地产', '制造', '农业'] for i, sector in enumerate(sectors): for j in range(8): heat_map_data.append({ 'sector': sector, 'metric': f'指标{j+1}', 'value': (i + j) % 10 + 1 }) return jsonify({ 'success': True, 'data': heat_map_data }) except Exception as e: print(f"Error getting heat map data: {e}") return jsonify({'success': False, 'error': str(e)}), 500 @bp.route('/correlation-analysis', methods=['GET']) def get_correlation_analysis(): """获取相关性分析""" try: date = request.args.get('date', '2025-07-16') # 模拟相关性分析数据 correlation_data = { 'sector_correlations': [ {'sector1': '科技', 'sector2': '新能源', 'correlation': 0.85}, {'sector1': '医药', 'sector2': '消费', 'correlation': 0.72}, {'sector1': '金融', 'sector2': '地产', 'correlation': 0.68}, {'sector1': '科技', 'sector2': '医药', 'correlation': 0.45}, {'sector1': '新能源', 'sector2': '制造', 'correlation': 0.78} ], 'stock_correlations': [ {'stock1': '000001', 'stock2': '000002', 'correlation': 0.92}, {'stock1': '000003', 'stock2': '000004', 'correlation': 0.88}, {'stock1': '000005', 'stock2': '000006', 'correlation': 0.76} ] } return jsonify({ 'success': True, 'data': correlation_data }) except Exception as e: print(f"Error getting correlation analysis: {e}") return jsonify({'success': False, 'error': str(e)}), 500 @bp.route('/export-data', methods=['POST']) def export_data(): """导出数据""" try: data = request.get_json() date = data.get('date', '2025-07-16') export_type = data.get('type', 'excel') # 模拟导出 filename = f'limit_analyse_{date}.{export_type}' return jsonify({ 'success': True, 'message': '数据导出成功', 'data': { 'filename': filename, 'download_url': f'/downloads/{filename}' } }) except Exception as e: print(f"Error exporting data: {e}") return jsonify({'success': False, 'error': str(e)}), 500 @bp.route('/high-position-stocks', methods=['GET']) def get_high_position_stocks(): """获取高位股统计数据""" try: date = request.args.get('date', datetime.now().strftime('%Y%m%d')) # 模拟高位股数据 - 实际使用时需要连接真实的数据库 # 根据用户提供的表结构,查询连续涨停天数较多的股票 high_position_stocks = [ { 'stock_code': '000001', 'stock_name': '平安银行', 'price': 15.68, 'increase_rate': 10.02, 'limit_up_days': 5, 'continuous_limit_up': 3, 'industry': '银行', 'turnover_rate': 3.45, 'market_cap': 32000000000 }, { 'stock_code': '000002', 'stock_name': '万科A', 'price': 18.92, 'increase_rate': 9.98, 'limit_up_days': 4, 'continuous_limit_up': 2, 'industry': '房地产', 'turnover_rate': 5.67, 'market_cap': 21000000000 }, { 'stock_code': '600036', 'stock_name': '招商银行', 'price': 42.15, 'increase_rate': 8.45, 'limit_up_days': 6, 'continuous_limit_up': 4, 'industry': '银行', 'turnover_rate': 2.89, 'market_cap': 105000000000 }, { 'stock_code': '000858', 'stock_name': '五粮液', 'price': 168.50, 'increase_rate': 7.23, 'limit_up_days': 3, 'continuous_limit_up': 2, 'industry': '白酒', 'turnover_rate': 1.56, 'market_cap': 650000000000 }, { 'stock_code': '002415', 'stock_name': '海康威视', 'price': 35.68, 'increase_rate': 6.89, 'limit_up_days': 4, 'continuous_limit_up': 3, 'industry': '安防', 'turnover_rate': 4.12, 'market_cap': 33000000000 } ] # 统计信息 total_count = len(high_position_stocks) avg_continuous_days = sum(stock['continuous_limit_up'] for stock in high_position_stocks) / total_count if total_count > 0 else 0 # 按连续涨停天数排序 high_position_stocks.sort(key=lambda x: x['continuous_limit_up'], reverse=True) return jsonify({ 'success': True, 'data': { 'stocks': high_position_stocks, 'statistics': { 'total_count': total_count, 'avg_continuous_days': round(avg_continuous_days, 2), 'max_continuous_days': max([stock['continuous_limit_up'] for stock in high_position_stocks], default=0), 'industry_distribution': {} } } }) except Exception as e: print(f"Error getting high position stocks: {e}") return jsonify({'success': False, 'error': str(e)}), 500