Download templates/scenario_predict.html from gitdeem/stock: direct link, hf CLI and curl.
- Browser
- Download file 15.1 kB
-
https://huggingface.co/spaces/gitdeem/stock/resolve/main/templates/scenario_predict.html
- Command line
-
hf download hf://spaces/gitdeem/stock/templates/scenario_predict.html
-
curl -L -o scenario_predict.html https://huggingface.co/spaces/gitdeem/stock/resolve/main/templates/scenario_predict.html
15.1 kB
| {% extends "layout.html" %} | |
| {% block title %}情景预测 - {{ stock_code }} - 智能分析系统{% endblock %} | |
| {% block content %} | |
| <div class="container-fluid py-3"> | |
| <div id="alerts-container"></div> | |
| <div class="row mb-3"> | |
| <div class="col-12"> | |
| <div class="card"> | |
| <div class="card-header py-2"> | |
| <h5 class="mb-0">多情景预测</h5> | |
| </div> | |
| <div class="card-body py-2"> | |
| <form id="scenario-form" class="row g-2"> | |
| <div class="col-md-3"> | |
| <div class="input-group input-group-sm"> | |
| <span class="input-group-text">股票代码</span> | |
| <input type="text" class="form-control" id="stock-code" placeholder="例如: 600519" required> | |
| </div> | |
| </div> | |
| <div class="col-md-3"> | |
| <div class="input-group input-group-sm"> | |
| <span class="input-group-text">市场</span> | |
| <select class="form-select" id="market-type"> | |
| <option value="A" selected>A股</option> | |
| <option value="HK">港股</option> | |
| <option value="US">美股</option> | |
| </select> | |
| </div> | |
| </div> | |
| <div class="col-md-3"> | |
| <div class="input-group input-group-sm"> | |
| <span class="input-group-text">预测天数</span> | |
| <select class="form-select" id="days"> | |
| <option value="30">30天</option> | |
| <option value="60" selected>60天</option> | |
| <option value="90">90天</option> | |
| <option value="180">180天</option> | |
| </select> | |
| </div> | |
| </div> | |
| <div class="col-md-3"> | |
| <button type="submit" class="btn btn-primary btn-sm w-100"> | |
| <i class="fas fa-chart-line"></i> 预测 | |
| </button> | |
| </div> | |
| </form> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="loading-panel" class="text-center py-5" style="display: none;"> | |
| <div class="spinner-border text-primary" role="status"> | |
| <span class="visually-hidden">Loading...</span> | |
| </div> | |
| <p class="mt-3 mb-0">正在生成预测结果...</p> | |
| <p class="text-muted small mt-2"> | |
| <i class="fas fa-info-circle"></i> | |
| AI分析需要一些时间,请耐心等待 | |
| </p> | |
| </div> | |
| <div id="scenario-result" style="display: none;"> | |
| <div class="row g-3 mb-3"> | |
| <div class="col-12"> | |
| <div class="card"> | |
| <div class="card-header py-2"> | |
| <h5 class="mb-0">价格预测图</h5> | |
| </div> | |
| <div class="card-body p-0"> | |
| <div id="price-prediction-chart" style="height: 400px;"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="row g-3 mb-3"> | |
| <div class="col-md-4"> | |
| <div class="card h-100"> | |
| <div class="card-header py-2 bg-success text-white"> | |
| <h5 class="mb-0">乐观情景</h5> | |
| </div> | |
| <div class="card-body"> | |
| <div class="d-flex justify-content-between mb-3"> | |
| <div> | |
| <h6>目标价</h6> | |
| <h3 id="optimistic-price" class="text-success">--</h3> | |
| </div> | |
| <div> | |
| <h6>预期涨幅</h6> | |
| <h3 id="optimistic-change" class="text-success">--</h3> | |
| </div> | |
| </div> | |
| <p id="optimistic-analysis" class="small"></p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="col-md-4"> | |
| <div class="card h-100"> | |
| <div class="card-header py-2 bg-primary text-white"> | |
| <h5 class="mb-0">中性情景</h5> | |
| </div> | |
| <div class="card-body"> | |
| <div class="d-flex justify-content-between mb-3"> | |
| <div> | |
| <h6>目标价</h6> | |
| <h3 id="neutral-price" class="text-primary">--</h3> | |
| </div> | |
| <div> | |
| <h6>预期涨幅</h6> | |
| <h3 id="neutral-change" class="text-primary">--</h3> | |
| </div> | |
| </div> | |
| <p id="neutral-analysis" class="small"></p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="col-md-4"> | |
| <div class="card h-100"> | |
| <div class="card-header py-2 bg-danger text-white"> | |
| <h5 class="mb-0">悲观情景</h5> | |
| </div> | |
| <div class="card-body"> | |
| <div class="d-flex justify-content-between mb-3"> | |
| <div> | |
| <h6>目标价</h6> | |
| <h3 id="pessimistic-price" class="text-danger">--</h3> | |
| </div> | |
| <div> | |
| <h6>预期涨幅</h6> | |
| <h3 id="pessimistic-change" class="text-danger">--</h3> | |
| </div> | |
| </div> | |
| <p id="pessimistic-analysis" class="small"></p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="row g-3 mb-3"> | |
| <div class="col-12"> | |
| <div class="card"> | |
| <div class="card-header py-2"> | |
| <h5 class="mb-0">风险与机会</h5> | |
| </div> | |
| <div class="card-body"> | |
| <div class="row"> | |
| <div class="col-md-6"> | |
| <h6 class="text-danger"><i class="fas fa-exclamation-triangle"></i> 风险因素</h6> | |
| <ul id="risk-factors" class="small"></ul> | |
| </div> | |
| <div class="col-md-6"> | |
| <h6 class="text-success"><i class="fas fa-lightbulb"></i> 有利因素</h6> | |
| <ul id="opportunity-factors" class="small"></ul> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| {% endblock %} | |
| {% block scripts %} | |
| <script> | |
| $(document).ready(function() { | |
| $('#scenario-form').submit(function(e) { | |
| e.preventDefault(); | |
| const stockCode = $('#stock-code').val().trim(); | |
| const marketType = $('#market-type').val(); | |
| const days = $('#days').val(); | |
| if (!stockCode) { | |
| showError('请输入股票代码!'); | |
| return; | |
| } | |
| fetchScenarioPrediction(stockCode, marketType, days); | |
| }); | |
| }); | |
| function fetchScenarioPrediction(stockCode, marketType, days) { | |
| $('#loading-panel').show(); | |
| $('#scenario-result').hide(); | |
| $.ajax({ | |
| url: '/api/scenario_predict', | |
| type: 'POST', | |
| contentType: 'application/json', | |
| data: JSON.stringify({ | |
| stock_code: stockCode, | |
| market_type: marketType, | |
| days: parseInt(days) | |
| }), | |
| success: function(response) { | |
| $('#loading-panel').hide(); | |
| renderScenarioPrediction(response, stockCode); | |
| $('#scenario-result').show(); | |
| }, | |
| error: function(xhr, status, error) { | |
| $('#loading-panel').hide(); | |
| let errorMsg = '获取情景预测失败'; | |
| if (xhr.responseJSON && xhr.responseJSON.error) { | |
| errorMsg += ': ' + xhr.responseJSON.error; | |
| } else if (error) { | |
| errorMsg += ': ' + error; | |
| } | |
| showError(errorMsg); | |
| } | |
| }); | |
| } | |
| function renderScenarioPrediction(data, stockCode) { | |
| // 设置乐观情景数据 | |
| $('#optimistic-price').text('¥' + formatNumber(data.optimistic.target_price, 2)); | |
| $('#optimistic-change').text(formatPercent(data.optimistic.change_percent, 2)); | |
| $('#optimistic-analysis').text(data.optimistic_analysis || '暂无分析'); | |
| // 设置中性情景数据 | |
| $('#neutral-price').text('¥' + formatNumber(data.neutral.target_price, 2)); | |
| $('#neutral-change').text(formatPercent(data.neutral.change_percent, 2)); | |
| $('#neutral-analysis').text(data.neutral_analysis || '暂无分析'); | |
| // 设置悲观情景数据 | |
| $('#pessimistic-price').text('¥' + formatNumber(data.pessimistic.target_price, 2)); | |
| $('#pessimistic-change').text(formatPercent(data.pessimistic.change_percent, 2)); | |
| $('#pessimistic-analysis').text(data.pessimistic_analysis || '暂无分析'); | |
| // 设置风险与机会因素 | |
| setDefaultRiskOpportunityFactors(); | |
| // 渲染价格预测图表 | |
| renderPricePredictionChart(data); | |
| } | |
| function setDefaultRiskOpportunityFactors() { | |
| // 示例风险因素 | |
| const riskFactors = [ | |
| '宏观经济下行压力增大', | |
| '行业政策收紧可能性', | |
| '原材料价格上涨', | |
| '市场竞争加剧', | |
| '技术迭代风险' | |
| ]; | |
| // 示例有利因素 | |
| const opportunityFactors = [ | |
| '行业景气度持续向好', | |
| '公司新产品上市', | |
| '成本控制措施见效', | |
| '产能扩张计划', | |
| '国际市场开拓机会' | |
| ]; | |
| // 填充HTML | |
| $('#risk-factors').html(''); | |
| riskFactors.forEach(factor => { | |
| $('#risk-factors').append(`<li>${factor}</li>`); | |
| }); | |
| $('#opportunity-factors').html(''); | |
| opportunityFactors.forEach(factor => { | |
| $('#opportunity-factors').append(`<li>${factor}</li>`); | |
| }); | |
| } | |
| function renderPricePredictionChart(data) { | |
| // 准备数据 | |
| const currentPrice = data.current_price; | |
| // 提取日期和价格路径 | |
| const dates = Object.keys(data.optimistic.path); | |
| const optimisticPrices = Object.values(data.optimistic.path); | |
| const neutralPrices = Object.values(data.neutral.path); | |
| const pessimisticPrices = Object.values(data.pessimistic.path); | |
| const options = { | |
| series: [ | |
| { | |
| name: '乐观情景', | |
| data: optimisticPrices.map((price, i) => ({ | |
| x: new Date(dates[i]), | |
| y: price | |
| })) | |
| }, | |
| { | |
| name: '中性情景', | |
| data: neutralPrices.map((price, i) => ({ | |
| x: new Date(dates[i]), | |
| y: price | |
| })) | |
| }, | |
| { | |
| name: '悲观情景', | |
| data: pessimisticPrices.map((price, i) => ({ | |
| x: new Date(dates[i]), | |
| y: price | |
| })) | |
| } | |
| ], | |
| chart: { | |
| height: 400, | |
| type: 'line', | |
| zoom: { | |
| enabled: true | |
| }, | |
| toolbar: { | |
| show: true | |
| } | |
| }, | |
| colors: ['#20E647', '#2E93fA', '#FF4560'], | |
| dataLabels: { | |
| enabled: false | |
| }, | |
| stroke: { | |
| curve: 'smooth', | |
| width: [3, 3, 3] | |
| }, | |
| title: { | |
| text: '多情景预测', | |
| align: 'left' | |
| }, | |
| grid: { | |
| borderColor: '#e7e7e7', | |
| row: { | |
| colors: ['#f3f3f3', 'transparent'], | |
| opacity: 0.5 | |
| }, | |
| }, | |
| markers: { | |
| size: 1 | |
| }, | |
| xaxis: { | |
| type: 'datetime', | |
| title: { | |
| text: '日期' | |
| } | |
| }, | |
| yaxis: { | |
| title: { | |
| text: '价格 (¥)' | |
| }, | |
| labels: { | |
| formatter: function(val) { | |
| return formatNumber(val, 2); | |
| } | |
| } | |
| }, | |
| legend: { | |
| position: 'top', | |
| horizontalAlign: 'right' | |
| }, | |
| tooltip: { | |
| shared: true, | |
| intersect: false, | |
| y: { | |
| formatter: function(value) { | |
| return '¥' + formatNumber(value, 2); | |
| } | |
| } | |
| }, | |
| annotations: { | |
| yaxis: [ | |
| { | |
| y: currentPrice, | |
| borderColor: '#000', | |
| label: { | |
| borderColor: '#000', | |
| style: { | |
| color: '#fff', | |
| background: '#000' | |
| }, | |
| text: '当前价格: ¥' + formatNumber(currentPrice, 2) | |
| } | |
| } | |
| ] | |
| } | |
| }; | |
| const chart = new ApexCharts(document.querySelector("#price-prediction-chart"), options); | |
| chart.render(); | |
| } | |
| </script> | |
| {% endblock %} |