|
|
|
@ -5,7 +5,7 @@ |
|
|
|
<meta name = "viewport" content = "width = device-width, initial-scale = 1.0"> |
|
|
|
<title>Kronos Financial Prediction Web UI</title> |
|
|
|
|
|
|
|
{# <script src = "https://cdn.plot.ly/plotly-latest.min.js"></script>#} |
|
|
|
<!--? <script src = "https://cdn.plot.ly/plotly-latest.min.js"></script>--> |
|
|
|
|
|
|
|
<script src = "https://cdn.plot.ly/plotly-2.27.0.min.js"></script> |
|
|
|
<script src = "https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> |
|
|
|
@ -157,6 +157,100 @@ |
|
|
|
background: linear-gradient(135deg, #ffc19d 0%, #ffc19d 100%); |
|
|
|
} |
|
|
|
|
|
|
|
/*表格弹窗样式*/ |
|
|
|
.search { |
|
|
|
display: flex; |
|
|
|
justify-content: space-between; |
|
|
|
align-items: center; |
|
|
|
margin-bottom: 8px; |
|
|
|
} |
|
|
|
|
|
|
|
.search-container{ |
|
|
|
white-space: nowrap; |
|
|
|
padding: 6px 12px; |
|
|
|
font-size: 14px; |
|
|
|
background-color: #8a94e0; |
|
|
|
color: white; |
|
|
|
border: none; |
|
|
|
border-radius: 6px; |
|
|
|
cursor: pointer; |
|
|
|
} |
|
|
|
|
|
|
|
.search-modal { |
|
|
|
display: none; |
|
|
|
position: fixed; |
|
|
|
top: 0; |
|
|
|
left: 0; |
|
|
|
width: 100%; |
|
|
|
height: 100%; |
|
|
|
background: rgba(0, 0, 0, 0.5); |
|
|
|
z-index: 1000; |
|
|
|
justify-content: center; |
|
|
|
align-items: center; |
|
|
|
} |
|
|
|
|
|
|
|
.search-modal-content { |
|
|
|
background: white; |
|
|
|
padding: 20px; |
|
|
|
border-radius: 10px; |
|
|
|
width: 90%; |
|
|
|
max-width: 1000px; |
|
|
|
max-height: 80vh; |
|
|
|
display: flex; |
|
|
|
flex-direction: column; |
|
|
|
text-align: center; |
|
|
|
} |
|
|
|
|
|
|
|
.search-modal-header { |
|
|
|
display: flex; |
|
|
|
justify-content: space-between; |
|
|
|
align-items: center; |
|
|
|
margin-bottom: 15px; |
|
|
|
} |
|
|
|
|
|
|
|
.search-modal-title { |
|
|
|
margin: 0; |
|
|
|
font-size: 1.5rem; |
|
|
|
} |
|
|
|
|
|
|
|
.close-modal-btn { |
|
|
|
background: #764ba2; |
|
|
|
color: white; |
|
|
|
border: none; |
|
|
|
padding: 5px 10px; |
|
|
|
border-radius: 5px; |
|
|
|
cursor: pointer; |
|
|
|
font-size: 1rem; |
|
|
|
} |
|
|
|
|
|
|
|
.search-results-container { |
|
|
|
overflow-y: auto; |
|
|
|
flex-grow: 1; |
|
|
|
} |
|
|
|
|
|
|
|
.rep-code { |
|
|
|
cursor: pointer; |
|
|
|
padding: 2px 8px; |
|
|
|
background: #f5f7fa; |
|
|
|
border-radius: 4px; |
|
|
|
font-size: 12px; |
|
|
|
color: #1989fa; |
|
|
|
transition: background 0.2s; |
|
|
|
display: inline-block; |
|
|
|
text-align: center; |
|
|
|
} |
|
|
|
|
|
|
|
.rep-code:hover { |
|
|
|
background: #e8f3ff; |
|
|
|
} |
|
|
|
|
|
|
|
.representative-codes { |
|
|
|
display: flex; |
|
|
|
flex-wrap: wrap; |
|
|
|
gap: 6px; |
|
|
|
justify-content: center; |
|
|
|
} |
|
|
|
|
|
|
|
.chart-grid { |
|
|
|
display: grid; |
|
|
|
grid-template-columns: 1fr auto; |
|
|
|
@ -525,9 +619,15 @@ |
|
|
|
<hr style = "margin: 20px 0; border: 1px solid #e2e8f0;"> |
|
|
|
|
|
|
|
|
|
|
|
<!-- Stock data acquisition --> |
|
|
|
<!-- 股票数据采集 --> |
|
|
|
<div class = "form-group"> |
|
|
|
<label class = "sr-only" for = "stock_code">Ticker Symbol Input:</label> |
|
|
|
<div class="search"> |
|
|
|
<label class="sr-only" for="stock_code">Ticker Symbol Input:</label> |
|
|
|
|
|
|
|
<button id="search-btn" class="search-container"> |
|
|
|
🔍 Search |
|
|
|
</button> |
|
|
|
</div> |
|
|
|
|
|
|
|
<input type = "text" class = "form-control" id = "stock_code" name = 'stock_code' |
|
|
|
value = "{{ stock_code }}" placeholder = "例如:sh.600000" > |
|
|
|
@ -539,6 +639,267 @@ |
|
|
|
📄 Stock Data |
|
|
|
</button> |
|
|
|
|
|
|
|
<!--股票数据提示弹窗--> |
|
|
|
<div id="search-modal" class="search-modal"> |
|
|
|
<div class="search-modal-content"> |
|
|
|
<div class="search-modal-header"> |
|
|
|
<h3 class="search-modal-title">📃 Stock Code Prompt:</h3> |
|
|
|
<button id="close-modal" class="close-modal-btn">×</button> |
|
|
|
</div> |
|
|
|
<div class="search-results-container"> |
|
|
|
<table class="comparison-table"> |
|
|
|
<thead> |
|
|
|
<tr> |
|
|
|
<th>Exchange</th> |
|
|
|
<th>Prefix</th> |
|
|
|
<th>Code_Range</th> |
|
|
|
<th>Representative_Code</th> |
|
|
|
</tr> |
|
|
|
</thead> |
|
|
|
|
|
|
|
<tbody id="search-results-body"> |
|
|
|
|
|
|
|
<!-- 上海证券交易所 (SSE)--> |
|
|
|
<tr> |
|
|
|
<td rowspan="5">上海证券交易所 (SSE)</td> |
|
|
|
<td rowspan="5">sh.</td> |
|
|
|
<td>600</td> |
|
|
|
<td class="representative-codes"> |
|
|
|
<span class="rep-code">sh.600000(浦发银行)</span> |
|
|
|
<span class="rep-code">sh.600036(招商银行)</span> |
|
|
|
<span class="rep-code">sh.600519(贵州茅台)</span> |
|
|
|
<span class="rep-code">sh.600887(伊利股份)</span> |
|
|
|
<span class="rep-code">sh.600900(长江电力)</span> |
|
|
|
<span class="rep-code">sh.600030(中信证券)</span> |
|
|
|
<span class="rep-code">sh.600050(中国联通)</span> |
|
|
|
<span class="rep-code">sh.600690(海尔智家)</span> |
|
|
|
<span class="rep-code">sh.600570(恒生电子)</span> |
|
|
|
<span class="rep-code">sh.600588(用友网络)</span> |
|
|
|
|
|
|
|
</td> |
|
|
|
</tr> |
|
|
|
<tr> |
|
|
|
<td>601</td> |
|
|
|
<td class="representative-codes"> |
|
|
|
<span class="rep-code">sh.601318(中国平安)</span> |
|
|
|
<span class="rep-code">sh.601398(工商银行)</span> |
|
|
|
<span class="rep-code">sh.601888(中国中免)</span> |
|
|
|
<span class="rep-code">sh.601857(中国石油)</span> |
|
|
|
<span class="rep-code">sh.601012(隆基绿能)</span> |
|
|
|
<span class="rep-code">sh.601988(中国国航)</span> |
|
|
|
<span class="rep-code">sh.601088(中国神华)</span> |
|
|
|
<span class="rep-code">sh.601766(中国中车)</span> |
|
|
|
<span class="rep-code">sh.601390(中国中铁)</span> |
|
|
|
<span class="rep-code">sh.601186(中国铁建)</span> |
|
|
|
|
|
|
|
</td> |
|
|
|
</tr> |
|
|
|
<tr> |
|
|
|
<td>603</td> |
|
|
|
<td class="representative-codes"> |
|
|
|
<span class="rep-code">sh.603288(海天味业)</span> |
|
|
|
<span class="rep-code">sh.603259(药明康德)</span> |
|
|
|
<span class="rep-code">sh.603986(兆易创新)</span> |
|
|
|
<span class="rep-code">sh.603501(韦尔股份)</span> |
|
|
|
<span class="rep-code">sh.603993(中科曙光)</span> |
|
|
|
<span class="rep-code">sh.603899(晨光股份)</span> |
|
|
|
<span class="rep-code">sh.603605(珀莱雅)</span> |
|
|
|
<span class="rep-code">sh.603707(健友股份)</span> |
|
|
|
<span class="rep-code">sh.603833(欧派家居)</span> |
|
|
|
<span class="rep-code">sh.603806(福斯特)</span> |
|
|
|
</td> |
|
|
|
</tr> |
|
|
|
<tr> |
|
|
|
<td>605</td> |
|
|
|
<td class="representative-codes"> |
|
|
|
<span class="rep-code">sh.605499(东鹏饮料)</span> |
|
|
|
<span class="rep-code">sh.605338(巴比食品)</span> |
|
|
|
<span class="rep-code">sh.605111(新洁能)</span> |
|
|
|
<span class="rep-code">sh.605589(圣泉集团)</span> |
|
|
|
<span class="rep-code">sh.605168(三人行)</span> |
|
|
|
<span class="rep-code">sh.605066(天正电气)</span> |
|
|
|
<span class="rep-code">sh.605155(西大门)</span> |
|
|
|
<span class="rep-code">sh.605136(丽人丽妆)</span> |
|
|
|
<span class="rep-code">sh.605333(沪光股份)</span> |
|
|
|
<span class="rep-code">sh.605358(立昂微)</span> |
|
|
|
</td> |
|
|
|
</tr> |
|
|
|
<tr> |
|
|
|
<td>688</td> |
|
|
|
<td class="representative-codes"> |
|
|
|
<span class="rep-code">sh.688012(中微公司)</span> |
|
|
|
<span class="rep-code">sh.688981(中芯国际)</span> |
|
|
|
<span class="rep-code">sh.688111(金山办公)</span> |
|
|
|
<span class="rep-code">sh.688036(传音控股)</span> |
|
|
|
<span class="rep-code">sh.688008(澜起科技)</span> |
|
|
|
<span class="rep-code">sh.688235(百济神州)</span> |
|
|
|
<span class="rep-code">sh.688185(康希诺)</span> |
|
|
|
<span class="rep-code">sh.688036(传音控股)</span> |
|
|
|
<span class="rep-code">sh.688187(时代电气)</span> |
|
|
|
<span class="rep-code">sh.688390(固德威)</span> |
|
|
|
</td> |
|
|
|
</tr> |
|
|
|
|
|
|
|
<!-- 深圳证券交易所 (SZSE)--> |
|
|
|
<tr> |
|
|
|
<td rowspan="5">深圳证券交易所</td> |
|
|
|
<td rowspan="5">sz.</td> |
|
|
|
<td>000</td> |
|
|
|
<td class="representative-codes"> |
|
|
|
<span class="rep-code">sz.000001(平安银行)</span> |
|
|
|
<span class="rep-code">sz.000002(万科A)</span> |
|
|
|
<span class="rep-code">sz.000858(五粮液)</span> |
|
|
|
<span class="rep-code">sz.000333(美的集团)</span> |
|
|
|
<span class="rep-code">sz.000651(格力电器)</span> |
|
|
|
<span class="rep-code">sz.000538(云南白药)</span> |
|
|
|
<span class="rep-code">sz.000063(中兴通讯)</span> |
|
|
|
<span class="rep-code">sz.000100(TCL科技)</span> |
|
|
|
<span class="rep-code">sz.000157(中联重科)</span> |
|
|
|
<span class="rep-code">sz.000895(双汇发展)</span> |
|
|
|
</td> |
|
|
|
</tr> |
|
|
|
<tr> |
|
|
|
<td>001</td> |
|
|
|
<td class="representative-codes"> |
|
|
|
<span class="rep-code">sz.001203(大中矿业)</span> |
|
|
|
<span class="rep-code">sz.001208(华菱线缆)</span> |
|
|
|
<span class="rep-code">sz.001212(中旗新材)</span> |
|
|
|
<span class="rep-code">sz.001213(中铁特货)</span> |
|
|
|
<span class="rep-code">sz.001215(千味央厨)</span> |
|
|
|
<span class="rep-code">sz.001217(华尔泰)</span> |
|
|
|
<span class="rep-code">sz.001218(丽臣实业)</span> |
|
|
|
<span class="rep-code">sz.001222(源飞宠物)</span> |
|
|
|
<span class="rep-code">sz.001225(和泰机电)</span> |
|
|
|
<span class="rep-code">sz.001309(德明利)</span> |
|
|
|
</td> |
|
|
|
</tr> |
|
|
|
<tr> |
|
|
|
<td>002</td> |
|
|
|
<td class="representative-codes"> |
|
|
|
<span class="rep-code">sz.002024(苏宁易购)</span> |
|
|
|
<span class="rep-code">sz.002027(分众传媒)</span> |
|
|
|
<span class="rep-code">sz.002555(三七互娱)</span> |
|
|
|
<span class="rep-code">sz.002624(完美世界)</span> |
|
|
|
<span class="rep-code">sz.002049(紫光国微)</span> |
|
|
|
<span class="rep-code">sz.002179(中航光电)</span> |
|
|
|
<span class="rep-code">sz.002415(海康威视)</span> |
|
|
|
<span class="rep-code">sz.002475(立讯精密)</span> |
|
|
|
<span class="rep-code">sz.002594(比亚迪)</span> |
|
|
|
<span class="rep-code">sz.002142(宁波银行)</span> |
|
|
|
</td> |
|
|
|
</tr> |
|
|
|
<tr> |
|
|
|
<td>003</td> |
|
|
|
<td class="representative-codes"> |
|
|
|
<span class="rep-code">sz.003816(中国广核)</span> |
|
|
|
<span class="rep-code">sz.003022(联泓新科)</span> |
|
|
|
<span class="rep-code">sz.003031(中瓷电子)</span> |
|
|
|
<span class="rep-code">sz.003032(传智教育)</span> |
|
|
|
<span class="rep-code">sz.003035(南网能源)</span> |
|
|
|
<span class="rep-code">sz.003036(泰坦股份)</span> |
|
|
|
<span class="rep-code">sz.003000(劲仔食品)</span> |
|
|
|
<span class="rep-code">sz.003001(中晶科技)</span> |
|
|
|
<span class="rep-code">sz.003002(传智教育)</span> |
|
|
|
<span class="rep-code">sz.003011(海象新材)</span> |
|
|
|
</td> |
|
|
|
</tr> |
|
|
|
<tr> |
|
|
|
<td>300</td> |
|
|
|
<td class="representative-codes"> |
|
|
|
<span class="rep-code">sz.300750(宁德时代)</span> |
|
|
|
<span class="rep-code">sz.300059(东方财富)</span> |
|
|
|
<span class="rep-code">sz.300124(汇川技术)</span> |
|
|
|
<span class="rep-code">sz.300760(迈瑞医疗)</span> |
|
|
|
<span class="rep-code">sz.300014(亿纬锂能)</span> |
|
|
|
<span class="rep-code">sz.300122(智飞生物)</span> |
|
|
|
<span class="rep-code">sz.300015(爱尔眼科)</span> |
|
|
|
<span class="rep-code">sz.300274(阳光电源)</span> |
|
|
|
<span class="rep-code">sz.300496(中科创达)</span> |
|
|
|
<span class="rep-code">sz.300782(卓胜微)</span> |
|
|
|
</td> |
|
|
|
</tr> |
|
|
|
|
|
|
|
<!--? 北京证券交易所 (BSE) --> |
|
|
|
<!--? <tr>--> |
|
|
|
<!--? <td rowspan="5">北京证券交易所 (BSE)</td>--> |
|
|
|
<!--? <td rowspan="5">bj.</td>--> |
|
|
|
<!--? <td>43</td>--> |
|
|
|
<!--? <td class="representative-codes">--> |
|
|
|
<!--? <span class="rep-code">bj.430047(诺思兰德)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.430090(同辉信息)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.430198(微创光电)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.430300(辰光医疗)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.430425(乐创技术)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.430476(海能技术)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.430510(丰光精密)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.430556(雅葆轩)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.430564(天润科技)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.430685(新芝生物)</span>--> |
|
|
|
<!--? </td>--> |
|
|
|
<!--? </tr>--> |
|
|
|
<!--? <tr>--> |
|
|
|
<!--? <td>83</td>--> |
|
|
|
<!--? <td class="representative-codes">--> |
|
|
|
<!--? <span class="rep-code">bj.830799(艾融软件)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.830809(安达科技)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.830839(万通液压)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.830866(齐鲁华信)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.830879(基康仪器)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.830896(旺成科技)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.830946(森萱医药)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.830964(润农节水)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.831010(凯添燃气)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.831039(国义招标)</span>--> |
|
|
|
<!--? </td>--> |
|
|
|
<!--? </tr>--> |
|
|
|
<!--? <tr>--> |
|
|
|
<!--? <td>87</td>--> |
|
|
|
<!--? <td class="representative-codes">--> |
|
|
|
<!--? <span class="rep-code">bj.870204(沪江材料)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.870357(雅葆轩)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.870436(大地电气)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.870640(曙光数创)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.870726(鸿智科技)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.870866(视声智能)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.870976(视声智能)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.871263(一致魔芋)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.871396(佳合科技)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.871478(海泰新能)</span>--> |
|
|
|
<!--? </td>--> |
|
|
|
<!--? </tr>--> |
|
|
|
<!--? <tr>--> |
|
|
|
<!--? <td>89</td>--> |
|
|
|
<!--? <td class="representative-codes">--> |
|
|
|
<!--? <span class="rep-code">bj.892089(科强股份)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.892282(美心翼申)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.892358(派诺科技)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.892519(捷众科技)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.892541(康农种业)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.892622(许昌智能)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.892679(云星宇)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.892748(欣捷高新)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.892810(捷安高科)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.892925(海昇药业)</span>--> |
|
|
|
<!--? </td>--> |
|
|
|
<!--? </tr>--> |
|
|
|
<!--? <tr>--> |
|
|
|
<!--? <td>920</td>--> |
|
|
|
<!--? <td class="representative-codes">--> |
|
|
|
<!--? <span class="rep-code">bj.920099(万达轴承)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.920175(欧福蛋业)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.920177(瑞华技术)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.920179(和特能源)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.920180(豪钢重工)</span>--> |
|
|
|
<!--? <span class="rep-code">bj.920179(和特能源)</span>--> |
|
|
|
<!--? </td>--> |
|
|
|
<!--? </tr>--> |
|
|
|
</tbody> |
|
|
|
</table> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<hr style="margin: 20px 0; border: 1px solid #e2e8f0;"> |
|
|
|
|
|
|
|
|
|
|
|
@ -702,6 +1063,7 @@ |
|
|
|
|
|
|
|
<br> |
|
|
|
|
|
|
|
<!--技术指标图表--> |
|
|
|
<h2>📶 Technical Indicator Chart</h2> |
|
|
|
|
|
|
|
<div id="indicator-status" class="indicator-status" style="display: none;"></div> |
|
|
|
@ -717,7 +1079,7 @@ |
|
|
|
<option value="Bollinger Bands (BB)">Bollinger Bands (BB)</option> |
|
|
|
<option value="Stochastic Oscillator (STOCH)">Stochastic Oscillator (STOCH)</option> |
|
|
|
<option value="Rolling Window Mean Strategy">Rolling Window Mean Strategy</option> |
|
|
|
<option value="TRIX Indicator (TRIX)">Triple Exponential Average (TRIX) Strategy</option> |
|
|
|
<option value="TRIX Indicator (TRIX)">TRIX Indicator (TRIX)</option> |
|
|
|
</select> |
|
|
|
|
|
|
|
<button id="generate-chart-btn" class="btn btn-warning"> |
|
|
|
@ -735,7 +1097,7 @@ |
|
|
|
|
|
|
|
<div id="indicator-chart"></div> |
|
|
|
|
|
|
|
<!-- Data Presentation --> |
|
|
|
<!-- 数据表格 --> |
|
|
|
<div id="data-presentation" class="comparison-section" style="display: none;"> |
|
|
|
<h3>💹 Financial Data Visualization</h3> |
|
|
|
|
|
|
|
@ -908,54 +1270,79 @@ |
|
|
|
|
|
|
|
//Stock Data按钮 |
|
|
|
document.addEventListener('DOMContentLoaded', function() { |
|
|
|
const generateChartBtn = document.getElementById('stock-data-btn'); |
|
|
|
if (generateChartBtn) { |
|
|
|
generateChartBtn.addEventListener('click', StockData); |
|
|
|
console.log('Stock Data button event listener bound'); |
|
|
|
} else { |
|
|
|
console.error('stock-data-btn element not found'); |
|
|
|
} |
|
|
|
}); |
|
|
|
const generateChartBtn = document.getElementById('stock-data-btn'); |
|
|
|
if (generateChartBtn) { |
|
|
|
generateChartBtn.addEventListener('click', StockData); |
|
|
|
console.log('Stock Data button event listener bound'); |
|
|
|
} else { |
|
|
|
console.error('stock-data-btn element not found'); |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
async function StockData() { |
|
|
|
console.log('Get stock data...'); |
|
|
|
const stockCodeInput = document.getElementById('stock_code'); |
|
|
|
const generateBtn = document.getElementById('stock-data-btn'); |
|
|
|
const stockCode = stockCodeInput.value.trim(); |
|
|
|
generateBtn.disabled = true; |
|
|
|
|
|
|
|
try { |
|
|
|
if (!stockCode) { |
|
|
|
showStatus('error', 'Stock code cannot be empty'); |
|
|
|
return; |
|
|
|
} |
|
|
|
console.log('Get stock data...'); |
|
|
|
const stockCodeInput = document.getElementById('stock_code'); |
|
|
|
const generateBtn = document.getElementById('stock-data-btn'); |
|
|
|
const stockCode = stockCodeInput.value.trim(); |
|
|
|
generateBtn.disabled = true; |
|
|
|
|
|
|
|
try { |
|
|
|
if (!stockCode) { |
|
|
|
showStatus('error', 'Stock code cannot be empty'); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
const stockCodeRegex = /^[a-z]+\.\d+$/; |
|
|
|
if (!stockCodeRegex.test(stockCode)) { |
|
|
|
showStatus('error', 'The ticker symbol is in the wrong format'); |
|
|
|
return; |
|
|
|
} |
|
|
|
const stockCodeRegex = /^[a-z]+\.\d+$/; |
|
|
|
if (!stockCodeRegex.test(stockCode)) { |
|
|
|
showStatus('error', 'The ticker symbol is in the wrong format'); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
showLoading(true); |
|
|
|
|
|
|
|
const response = await axios.post('/api/stock-data', {stock_code: stockCode}); |
|
|
|
|
|
|
|
if (response.data.success) { |
|
|
|
showStatus('success', `Successfully fetched data for ${stockCode}`); |
|
|
|
loadDataFiles(); |
|
|
|
stockCodeInput.value = ''; |
|
|
|
} else { |
|
|
|
showStatus('error', response.data.error || 'Failed to fetch stock data'); |
|
|
|
} |
|
|
|
} catch (error) { |
|
|
|
console.error('❌ Failed to fetch stock data:', error); |
|
|
|
showStatus('error', `Failed to fetch data`); |
|
|
|
} finally { |
|
|
|
showLoading(false); |
|
|
|
if (generateBtn) generateBtn.disabled = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
showLoading(true); |
|
|
|
|
|
|
|
const response = await axios.post('/api/stock-data', {stock_code: stockCode}); |
|
|
|
// Search按钮表格弹窗 |
|
|
|
document.addEventListener('DOMContentLoaded', function() { |
|
|
|
const searchBtn = document.getElementById('search-btn'); |
|
|
|
const searchModal = document.getElementById('search-modal'); |
|
|
|
const closeModal = document.getElementById('close-modal'); |
|
|
|
const stockCodeInput = document.getElementById('stock_code'); |
|
|
|
|
|
|
|
if (response.data.success) { |
|
|
|
showStatus('success', `Successfully fetched data for ${stockCode}`); |
|
|
|
loadDataFiles(); |
|
|
|
stockCodeInput.value = ''; |
|
|
|
} else { |
|
|
|
showStatus('error', response.data.error || 'Failed to fetch stock data'); |
|
|
|
} |
|
|
|
} catch (error) { |
|
|
|
console.error('❌ Failed to fetch stock data:', error); |
|
|
|
showStatus('error', `Failed to fetch data`); |
|
|
|
} finally { |
|
|
|
showLoading(false); |
|
|
|
if (generateBtn) generateBtn.disabled = false; |
|
|
|
} |
|
|
|
searchBtn.addEventListener('click', () => { |
|
|
|
searchModal.style.display = 'flex'; |
|
|
|
}); |
|
|
|
|
|
|
|
closeModal.addEventListener('click', () => { |
|
|
|
searchModal.style.display = 'none'; |
|
|
|
}); |
|
|
|
|
|
|
|
document.addEventListener('click', (e) => { |
|
|
|
if (e.target.classList.contains('rep-code')) { |
|
|
|
const code = e.target.textContent.match(/[a-z]+\.\d+/)[0]; |
|
|
|
stockCodeInput.value = code; |
|
|
|
closeModalFunc(); |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// Load data file list |
|
|
|
@ -1262,7 +1649,7 @@ |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// Generate technical chart |
|
|
|
// 技术指标图表 |
|
|
|
async function generateTechnicalChart() { |
|
|
|
console.log('Generating technical indicator chart...'); |
|
|
|
|
|
|
|
@ -1275,7 +1662,6 @@ |
|
|
|
try { |
|
|
|
await new Promise(resolve => setTimeout(resolve, 2000)); |
|
|
|
|
|
|
|
// get arguments |
|
|
|
const startHandle = document.getElementById('start-handle'); |
|
|
|
const endHandle = document.getElementById('end-handle'); |
|
|
|
|
|
|
|
@ -1292,11 +1678,10 @@ |
|
|
|
const filePath = document.getElementById('data-file-select').value; |
|
|
|
const diagramType = document.getElementById('diagram_type').value; |
|
|
|
|
|
|
|
// validate arguments |
|
|
|
if (!filePath) throw new Error('Please select a data file first'); |
|
|
|
if (isNaN(lookback) || isNaN(predLen)) throw new Error('Invalid parameters'); |
|
|
|
|
|
|
|
// fetch chart data |
|
|
|
// 获取接口 |
|
|
|
const response = await fetch('/api/generate-chart', { |
|
|
|
method: 'POST', |
|
|
|
headers: { 'Content-Type': 'application/json' }, |
|
|
|
@ -1312,7 +1697,7 @@ |
|
|
|
const result = await response.json(); |
|
|
|
if (!result.success) throw new Error(result.error || 'Failed to generate chart'); |
|
|
|
|
|
|
|
// render the chart |
|
|
|
// 渲染图标 |
|
|
|
const chartContainer = document.getElementById('indicator-chart'); |
|
|
|
if (chartContainer) { |
|
|
|
if (chartContainer.data) Plotly.purge(chartContainer); |
|
|
|
@ -1347,7 +1732,7 @@ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Fill data table |
|
|
|
// 数据表格 |
|
|
|
function fillDataTable(data) { |
|
|
|
const tbody = document.getElementById('data-tbody'); |
|
|
|
|
|
|
|
|