import sys from django.shortcuts import render from django.http import HttpResponse from rest_framework.decorators import api_view from rest_framework.response import Response from drf_spectacular.utils import extend_schema, OpenApiParameter, OpenApiTypes from .stock.stock_utils import viewFunc_tsCodeAndDate, viewFunc_singleParam from .stock.stock_basic import getStockBasic, getStockListByIndustry, getStockInfo from .stock.getStockParam import getStockParam from .stock.getStockEp import getStockEp_ttm, get_quarterly_eps from .stock.getIndexs import get_index_daily_data, get_index_by_name from .stock.stockMargin import getStockMargin, getDailyMargin from .stock.getStockFina import get_finance_data_range from .stock.getStockDiv2 import analyze_stock_dividend_and_price from .stock.xwlbDaily import get_xwlb, get_xwlb_fine from .stock.getDivData_AK import get_akshare_dividend_yield from .serializers import ( StockDailySerializer, StockInfoSerializer, IndustryStockSerializer, StockParamSerializer, StockEpSerializer, QuarterlyEpsSerializer, IndexInfoSerializer, IndexDailySerializer, MarginDailySerializer, StockMarginSerializer, FinanceDataSerializer, DividendSerializer, XwlbNewsSerializer, ) # === 通用参数定义(复用) === _PARAM_TSCODE = OpenApiParameter(name='tscode', type=str, default='000001.SZ', description='股票代码,如 000001.SZ') _PARAM_INDEX_CODE = OpenApiParameter(name='tscode', type=str, default='000001.SH', description='指数代码,如 000001.SH=上证指数, 399001.SZ=深证成指, 399006.SZ=创业板指') _PARAM_START = OpenApiParameter(name='start_date', type=str, default='20200101', description='起始日期 yyyyMMdd') _PARAM_END = OpenApiParameter(name='end_date', type=str, default='20251231', description='结束日期 yyyyMMdd') _PARAM_INDEX_NAME = OpenApiParameter(name='index_name', type=str, default='沪深300', description='指数名称,如 沪深300、上证50') _PARAM_INDUSTRY = OpenApiParameter(name='industry', type=str, required=True, description='行业名称,如 银行、半导体') _PARAM_TRADE_DATE = OpenApiParameter(name='trade_date', type=str, description='交易日期 yyyyMMdd') _PARAM_EXCHANGE_ID = OpenApiParameter(name='exchange_id', type=str, description='交易所代码 SSE/SZSE') @extend_schema( responses={200: OpenApiTypes.STR}, description='返回服务器 Python 版本', tags=['系统'], ) @api_view(['GET']) def python_version(request): return HttpResponse(f"Python Version: {sys.version}") @extend_schema(exclude=True) @api_view(['GET']) def home(request): return render(request, 'home.html') @extend_schema( parameters=[_PARAM_TSCODE, _PARAM_START, _PARAM_END], responses={200: StockDailySerializer(many=True)}, description='获取个股日线行情数据(开高低收、成交量、成交额)', tags=['行情'], ) @api_view(['GET']) def stockbasic(request): return viewFunc_tsCodeAndDate(request, getStockBasic) @extend_schema( parameters=[_PARAM_INDUSTRY], responses={200: IndustryStockSerializer(many=True)}, description='按申万行业分类查询成分股列表', tags=['基础数据'], ) @api_view(['GET']) def industrys(request): return viewFunc_singleParam(request, getStockListByIndustry, param_name='industry') @extend_schema( parameters=[_PARAM_TSCODE], responses={200: StockInfoSerializer()}, description='获取个股基本信息(名称、行业、上市日期、交易所等)', tags=['基础数据'], ) @api_view(['GET']) def stockInfo(request): return viewFunc_singleParam(request, getStockInfo, param_name='tscode') @extend_schema( parameters=[_PARAM_TSCODE, _PARAM_START, _PARAM_END], responses={200: StockParamSerializer(many=True)}, description='获取个股每日参数(市值、PE/PB/PS、换手率等)', tags=['行情'], ) @api_view(['GET']) def stockparam(request): return viewFunc_tsCodeAndDate(request, getStockParam) @extend_schema( parameters=[_PARAM_TSCODE, _PARAM_START, _PARAM_END], responses={200: StockEpSerializer(many=True)}, description='获取个股 TTM 每股收益(EPS)', tags=['财务'], ) @api_view(['GET']) def stockep(request): return viewFunc_tsCodeAndDate(request, getStockEp_ttm) @extend_schema( parameters=[_PARAM_TSCODE, _PARAM_START, _PARAM_END], responses={200: QuarterlyEpsSerializer(many=True)}, description='获取个股季度每股收益(EPS),按财报日期对齐', tags=['财务'], ) @api_view(['GET']) def quarterlyEps(request): return viewFunc_tsCodeAndDate(request, get_quarterly_eps) @extend_schema( parameters=[_PARAM_INDEX_NAME], responses={200: IndexInfoSerializer()}, description='按名称模糊查询指数基本信息', tags=['指数'], ) @api_view(['GET']) def indexByName(request): index_name = request.GET.get('index_name', '沪深300') if not index_name: return Response({'error': '缺少 index_name 参数'}, status=400) try: data = get_index_by_name(index_name) dict_data = data.to_dict(orient='records') return Response(dict_data) except ImportError: return Response({'error': '模块不存在'}, status=500) except Exception as e: return Response({'error': str(e)}, status=500) @extend_schema( parameters=[_PARAM_INDEX_CODE, _PARAM_START, _PARAM_END], responses={200: IndexDailySerializer(many=True)}, description='获取指数日线行情数据(含 PE/PB/市值/换手率等扩展指标)', tags=['指数'], ) @api_view(['GET']) def indexDatas(request): return viewFunc_tsCodeAndDate(request, get_index_daily_data) @extend_schema( parameters=[_PARAM_TSCODE, _PARAM_START, _PARAM_END], responses={200: StockMarginSerializer(many=True)}, description='获取个股融资融券明细数据', tags=['融资融券'], ) @api_view(['GET']) def stockMargin(request): return viewFunc_tsCodeAndDate(request, getStockMargin) @extend_schema( parameters=[_PARAM_TRADE_DATE, _PARAM_START, _PARAM_END, _PARAM_EXCHANGE_ID], responses={200: MarginDailySerializer(many=True)}, description='获取每日融资融券汇总数据(按交易所)', tags=['融资融券'], ) @api_view(['GET']) def dailyMargin(request): trade_date = request.GET.get('trade_date', None) start_date = request.GET.get('start_date', None) end_date = request.GET.get('end_date', None) exchange_id = request.GET.get('exchange_id', None) try: data = getDailyMargin(trade_date=trade_date, start_date=start_date, end_date=end_date, exchange_id=exchange_id) dict_data = data.to_dict(orient='records') return Response(dict_data) except ImportError: return Response({'error': '模块不存在'}, status=500) except Exception as e: return Response({'error': str(e)}, status=500) @extend_schema( parameters=[_PARAM_TSCODE, _PARAM_START, _PARAM_END], responses={200: FinanceDataSerializer(many=True)}, description='获取个股财务报表分析数据(资产负债表+利润表+现金流,含运营/资产/负债/回报率指标)', tags=['财务'], ) @api_view(['GET']) def getFinaData(request): return viewFunc_tsCodeAndDate(request, get_finance_data_range) @extend_schema( parameters=[_PARAM_TSCODE, _PARAM_START, _PARAM_END], responses={200: DividendSerializer(many=True)}, description='获取个股股息率数据(含 TTM 分红、收盘价、股息率)', tags=['分红'], ) @api_view(['GET']) def getDivData(request): return viewFunc_tsCodeAndDate(request, analyze_stock_dividend_and_price) @extend_schema( parameters=[_PARAM_TSCODE, _PARAM_START, _PARAM_END], responses={200: DividendSerializer(many=True)}, description='获取个股股息率数据(akshare 数据源,无需 token)', tags=['分红'], ) @api_view(['GET']) def getDivDataAkshare(request): return viewFunc_tsCodeAndDate(request, get_akshare_dividend_yield) def _xwlb_view(request, data_func): start_date = request.GET.get('start_date', None) end_date = request.GET.get('end_date', None) try: data = data_func(start_date=start_date, end_date=end_date) dict_data = data.to_dict(orient='records') status = "success" if dict_data else "Error" return Response({"status": status, "data": {"news": dict_data}}) except ImportError: return Response({'error': '模块不存在'}, status=500) except Exception as e: return Response({'error': str(e)}, status=500) @extend_schema( parameters=[_PARAM_START, _PARAM_END], responses={200: XwlbNewsSerializer(many=True)}, description='获取新闻联播原始识别文本(ASR 转写结果)', tags=['新闻联播'], ) @api_view(['GET']) def xwlbNews(request): return _xwlb_view(request, get_xwlb) @extend_schema( parameters=[_PARAM_START, _PARAM_END], responses={200: XwlbNewsSerializer(many=True)}, description='获取新闻联播精编内容(AI 分割+标题提取后的独立新闻)', tags=['新闻联播'], ) @api_view(['GET']) def xwlbFine(request): return _xwlb_view(request, get_xwlb_fine)