- 删除重复库文件:lib/DataTables-2/、lib/echarts/、libai/、css/fontawesome/ 等 179 个冗余文件 - 下载外部 CDN 到本地:Mermaid、AOS、Google Fonts(Inter/Noto Serif SC/Noto Sans SC) - 所有第三方库统一到 lib/,按库名-版本号命名 - 更新 8 个 research HTML 文件引用路径 - stock_his_pro → /api/stockbasic/(getStockHist、recentPrice) - stock_all_pro → /api/stockinfo/(tscodeToName) - index_hist_pro → /api/indexDatas/(getIndexData) - 新增 callDoorcomeApi() 共享函数 - 被替换表的 DB 查询代码完全删除,无回退 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
259 lines
8.5 KiB
PHP
259 lines
8.5 KiB
PHP
<?php
|
|
include_once __DIR__."/config.php";
|
|
include_once __DIR__."/functions.inc.php";
|
|
include_once __DIR__."/widgets.inc.php";
|
|
|
|
/**
|
|
* 获取PE_TTM,PB,PS等历史数据
|
|
* @param $ts_code ts code
|
|
* @param $day_st start date
|
|
* @param $day_end end date
|
|
* @param $item: PE_TTM, PB,PS
|
|
* @return array
|
|
*/
|
|
function getBasicData($ts_code,$day_st,$day_end,$item){
|
|
$allowed_items = ['PE_TTM', 'PB', 'PS', 'pe_ttm', 'pb', 'ps'];
|
|
if(!in_array($item, $allowed_items)) return array('tDate'=>[],'idx'=>[],'data'=>[],'data_max'=>0,'data_min'=>0,'data_avg'=>0,'data_last'=>0);
|
|
|
|
$day_st=date('Ymd',strtotime($day_st));
|
|
$mysqli = get_mysqli_connection();
|
|
$sql = "select DATE_FORMAT(trade_date,'%Y-%m-%d') as trade_date, $item as pe_ttm from stock_his_basic_pro where ts_code = ? and trade_date > ?";
|
|
$params = [$ts_code, $day_st];
|
|
if($day_end) {
|
|
$day_end=date('Ymd',strtotime($day_end));
|
|
$sql .= " and trade_date < ?";
|
|
$params[] = $day_end;
|
|
}
|
|
$sql .= " order by trade_date asc";
|
|
$result = db_query($mysqli, $sql, $params);
|
|
|
|
$tDate=$idx=$data=$data_clean=array(); # $data_clean is an array without null
|
|
|
|
if($result && $result->num_rows>0) {
|
|
#$data = $result->fetch_all();
|
|
while($row=$result->fetch_assoc()){
|
|
$trade_date=$row['trade_date'];
|
|
#$trade_date=substr($row['trade_date'],0,4).'-'.substr($row['trade_date'],4,2).'-'.substr($row['trade_date'],6,2);
|
|
#$trade_date1=strtotime($row['trade_date']);
|
|
array_push($tDate,$trade_date);
|
|
array_push($idx,$row['pe_ttm']);
|
|
$data_tmp = array("value"=>array($trade_date,$row['pe_ttm']));
|
|
array_push($data,$data_tmp);
|
|
if($data_tmp['value'][1]>0) array_push($data_clean,$data_tmp['value'][1]);
|
|
}
|
|
}
|
|
$data_last= round($data_clean[count($data_clean)-1],2);
|
|
$data_max= round(max($data_clean),2);
|
|
$data_min= round(min($data_clean),2);
|
|
if(count($data_clean)>0) $data_avg= round(array_sum($data_clean)/count($data_clean),2);
|
|
else $data_avg=null;
|
|
#Free result and close connection.
|
|
$result->free();
|
|
$mysqli->close();
|
|
return array('tDate'=>$tDate,'idx'=>$idx,'data'=>$data,'data_max'=>$data_max,'data_min'=>$data_min,'data_avg'=>$data_avg,'data_last'=>$data_last);
|
|
}
|
|
|
|
|
|
|
|
function ts_code_conv($ts_code){
|
|
$tmp = explode('.',$ts_code);
|
|
switch($tmp[1]){
|
|
case 'SZ':
|
|
return $ts_code;
|
|
case 'SH':
|
|
return $ts_code;
|
|
case 'sz':
|
|
return strtoupper($ts_code);
|
|
case 'sh':
|
|
return strtoupper($ts_code);
|
|
default:
|
|
if(substr($tmp[0],0,2)=='60') return $tmp[0].'.SH';
|
|
elseif(substr($tmp[0],0,2)=='30') return $tmp[0].'.SZ';
|
|
elseif(substr($tmp[0],0,2)=='00') return $tmp[0].'.SZ';
|
|
else return $ts_code;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
function getStockHist($ts_code,$day_st,$day_end){
|
|
$tDate=$idx=$data=array();
|
|
$ds = preg_replace('/\D/', '', $day_st);
|
|
$de = $day_end ? preg_replace('/\D/', '', $day_end) : date('Ymd');
|
|
$resp = callDoorcomeApi('stockbasic', ['tscode' => $ts_code, 'start_date' => $ds, 'end_date' => $de]);
|
|
if ($resp && is_array($resp)) {
|
|
foreach ($resp as $row) {
|
|
$d = $row['trade_date'];
|
|
array_push($tDate, $d);
|
|
array_push($idx, $row['close']);
|
|
array_push($data, ["value" => [$d, $row['close']]]);
|
|
}
|
|
}
|
|
return array('tDate'=>$tDate,'idx'=>$idx,'data'=>$data);
|
|
}
|
|
|
|
function tscodeToName($ts_code){
|
|
$resp = callDoorcomeApi('stockinfo', ['tscode' => $ts_code]);
|
|
if ($resp && isset($resp[0]['name'])) {
|
|
return $resp[0]['name'];
|
|
}
|
|
return $ts_code;
|
|
}
|
|
|
|
}
|
|
|
|
function getBasicExtData($ts_code,$item,$day_st,$day_end){
|
|
$mysqli = get_mysqli_connection();
|
|
$allowed_items = ['total_mv','circ_mv','total_mv_all','circ_mv_all','pe_ttm','pb','ps','total_share','float_share','free_share'];
|
|
if(!in_array($item, $allowed_items)) return array('tDate'=>[],'idx'=>[],'data'=>[],'data_max'=>0,'data_min'=>0,'data_avg'=>0,'data_last'=>0);
|
|
|
|
$extra_where = "";
|
|
if($item=='total_mv_all' or $item=='circ_mv_all') {
|
|
$extra_where = " and vol/10000/10000 > 1";
|
|
$ts_code='all';
|
|
$item=substr($item,0,-4);
|
|
}
|
|
$sql = "select * from stock_basic_ext where code = ? and item = ? and trade_date > ?";
|
|
$params = [$ts_code, $item, $day_st];
|
|
if($day_end) {
|
|
$sql .= " and trade_date < ?";
|
|
$params[] = $day_end;
|
|
}
|
|
$sql .= $extra_where . " order by trade_date asc";
|
|
$result = db_query($mysqli, $sql, $params);
|
|
|
|
$tDate=$idx=$data=array();
|
|
|
|
if($result && $result->num_rows>0) {
|
|
#$data = $result->fetch_all();
|
|
while($row=$result->fetch_assoc()){
|
|
if($item=='total_mv' or $item=='circ_mv') {
|
|
$row['vol']=$row['vol']/10000/10000; #单位:亿
|
|
}
|
|
$trade_date=substr($row['trade_date'],0,4).'-'.substr($row['trade_date'],4,2).'-'.substr($row['trade_date'],6,2);
|
|
#$trade_date=substr($row['trade_date'],0,4).'-'.substr($row['trade_date'],4,2).'-'.substr($row['trade_date'],6,2);
|
|
$trade_date=substr($row['trade_date'],0,10);
|
|
array_push($tDate,$trade_date);
|
|
array_push($idx,$row['vol']);
|
|
array_push($data,array("value"=>array($trade_date,round($row['vol'],2))));
|
|
}
|
|
}
|
|
#Free result and close connection.
|
|
$result->free();
|
|
$mysqli->close();
|
|
$data_last= round($idx[count($idx)-1],2);
|
|
$data_max= round(max($idx),2);
|
|
$data_min= round(min($idx),2);
|
|
if(count($idx)>0) $data_avg= round(array_sum($idx)/count($idx),2);
|
|
return array('tDate'=>$tDate,'idx'=>$idx,'data'=>$data,'data_max'=>$data_max,'data_min'=>$data_min,'data_avg'=>$data_avg,'data_last'=>$data_last);
|
|
}
|
|
|
|
/**
|
|
* @param $date : given a date (yyyy-mm-dd)
|
|
* @param $gap : days +/- n(int)
|
|
* @return false|string
|
|
*/
|
|
function dateGap($date,$gap){
|
|
$str="$date $gap day";
|
|
return date('Y-m-d',strtotime($str));//日期天数相加函数
|
|
|
|
}
|
|
|
|
|
|
|
|
// 函数一:获取股票代码ts_code对应的历史pe_ttm、pb或ps
|
|
function getStockHistoryDataByTS($ts_code, $day_st, $item, $day_end = null){
|
|
//global $token;
|
|
|
|
// 参数校验
|
|
if (empty($ts_code) || empty($day_st) || !in_array(strtolower($item), ['pe_ttm', 'pb', 'ps'])) {
|
|
return "参数错误:股票代码、起始日期不能为空,查询项目必须为pe_ttm、pb或ps。";
|
|
}
|
|
|
|
// 处理日期参数
|
|
$params = [
|
|
"ts_code" => $ts_code,
|
|
"start_date" => $day_st,
|
|
"end_date" => $day_end ?? date("Y-m-d") // 如果为空,默认为今天
|
|
];
|
|
|
|
// 调用TuShare API获取数据
|
|
$data = callTushareApi('daily_basic', $params);
|
|
return true ;
|
|
if (empty($data)) {
|
|
return "未获取到数据,请检查参数或网络连接。";
|
|
}
|
|
|
|
// 提取指定项目的数据
|
|
$result = [];
|
|
$tDate = [];
|
|
$itemValues = [];
|
|
foreach ($data as $row) {
|
|
$tDate[] = $row['trade_date'];
|
|
$itemValues[] = $row[$item];
|
|
}
|
|
|
|
// 按日期排序(从远到近,默认已经是按日期排序的)
|
|
$tDate = array_reverse($tDate); // 默认TuShare按日期顺序是近到远,所以反转得到远到近
|
|
$itemValues = array_reverse($itemValues);
|
|
|
|
// 计算统计值
|
|
$dataMax = max($itemValues);
|
|
$dataMin = min($itemValues);
|
|
$dataAvg = array_sum($itemValues) / count($itemValues);
|
|
$dataLast = end($itemValues);
|
|
|
|
// 返回结果
|
|
return [
|
|
'tDate' => $tDate,
|
|
'data' => $itemValues,
|
|
'data_max' => $dataMax,
|
|
'data_min' => $dataMin,
|
|
'data_avg' => $dataAvg,
|
|
'data_last' => $dataLast
|
|
];
|
|
}
|
|
|
|
// 函数二:获取指数趋势历史数据
|
|
function getIndexHistoryDataByTS($ts_code, $day_st, $day_end = null)
|
|
{
|
|
global $token;
|
|
|
|
// 参数校验
|
|
if (empty($ts_code) || empty($day_st)) {
|
|
return "参数错误:股票代码和起始日期不能为空。";
|
|
}
|
|
|
|
// 处理日期参数
|
|
$params = [
|
|
"ts_code" => $ts_code,
|
|
"start_date" => $day_st,
|
|
"end_date" => $day_end ?? date("Y-m-d") // 如果为空,默认为今天
|
|
];
|
|
|
|
// 调用TuShare API获取数据
|
|
$data = callTushareApi('index_dailybasic', $params);
|
|
return true ;
|
|
if (empty($data)) {
|
|
return "未获取到数据,请检查参数或网络连接。";
|
|
}
|
|
|
|
// 提取指数点数值
|
|
$tDate = [];
|
|
$closeValues = [];
|
|
foreach ($data as $row) {
|
|
$tDate[] = $row['trade_date'];
|
|
$closeValues[] = $row['close']; // 假设close字段是指数点数值
|
|
}
|
|
|
|
// 按日期排序
|
|
$tDate = array_reverse($tDate);
|
|
$closeValues = array_reverse($closeValues);
|
|
|
|
// 返回结果
|
|
return [
|
|
'tDate' => $tDate,
|
|
'data' => $closeValues
|
|
];
|
|
}
|
|
?>
|