mirror of
https://github.com/ArvinLovegood/go-stock.git
synced 2025-07-19 00:00:09 +08:00
feat(stock):优化股票分时图表展示
- 新增 GetStockMinutePriceLineData 函数获取股票分时数据 - 在前端实现分时数据图表展示 - 后端增加 GetStockMinutePriceData接口获取分时数据 - 更新数据库模型,添加 MinuteData 结构体
This commit is contained in:
parent
11a1a47eca
commit
cf537ca695
11
app.go
11
app.go
@ -1065,6 +1065,17 @@ func (a *App) RemoveGroup(groupId int) string {
|
||||
func (a *App) GetStockKLine(stockCode, stockName string, days int64) *[]data.KLineData {
|
||||
return data.NewStockDataApi().GetHK_KLineData(stockCode, "day", days)
|
||||
}
|
||||
|
||||
func (a *App) GetStockMinutePriceLineData(stockCode, stockName string) map[string]any {
|
||||
res := make(map[string]any, 4)
|
||||
priceData, date := data.NewStockDataApi().GetStockMinutePriceData(stockCode)
|
||||
res["priceData"] = priceData
|
||||
res["date"] = date
|
||||
res["stockName"] = stockName
|
||||
res["stockCode"] = stockCode
|
||||
return res
|
||||
}
|
||||
|
||||
func (a *App) GetStockCommonKLine(stockCode, stockName string, days int64) *[]data.KLineData {
|
||||
return data.NewStockDataApi().GetCommonKLineData(stockCode, "day", days)
|
||||
}
|
||||
|
@ -1235,6 +1235,66 @@ func CheckBrowserOnWindows() (string, bool) {
|
||||
return path + "\\msedge.exe", true
|
||||
}
|
||||
|
||||
// 分时数据
|
||||
func (receiver StockDataApi) GetStockMinutePriceData(stockCode string) (*[]MinuteData, string) {
|
||||
url := fmt.Sprintf("https://web.ifzq.gtimg.cn/appstock/app/minute/query?code=%s", stockCode)
|
||||
if strutil.HasPrefixAny(stockCode, []string{"gb_", "GB_"}) {
|
||||
stockCode = strings.Replace(strings.ToUpper(stockCode), "GB_", "us", 1) + ".OQ"
|
||||
}
|
||||
if strutil.HasPrefixAny(stockCode, []string{"us", "US"}) {
|
||||
url = fmt.Sprintf("https://web.ifzq.gtimg.cn/appstock/app/UsMinute/query?code=%s", stockCode)
|
||||
}
|
||||
logger.SugaredLogger.Infof("GetStockMinutePriceData url:%s", url)
|
||||
res := make(map[string]interface{})
|
||||
resp, err := receiver.client.SetTimeout(time.Duration(receiver.config.CrawlTimeOut)*time.Second).R().
|
||||
SetHeader("Host", "web.ifzq.gtimg.cn").
|
||||
SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0").
|
||||
Get(url)
|
||||
|
||||
date := ""
|
||||
minuteDatas := &[]MinuteData{}
|
||||
|
||||
if err != nil {
|
||||
logger.SugaredLogger.Errorf("err:%s", err.Error())
|
||||
return minuteDatas, date
|
||||
}
|
||||
//logger.SugaredLogger.Infof("resp:%s", resp.Body())
|
||||
json.Unmarshal(resp.Body(), &res)
|
||||
code, _ := convertor.ToInt(res["code"])
|
||||
if res["data"] != nil && code == 0 {
|
||||
data := res["data"].(map[string]interface{})
|
||||
if stockData, ok := data[stockCode]; ok {
|
||||
m := stockData.(map[string]interface{})
|
||||
if d, ok := m["data"]; ok {
|
||||
if m2, ok := d.(map[string]any); ok {
|
||||
minutePriceData := m2["data"]
|
||||
datas := minutePriceData.([]any)
|
||||
for _, item := range datas {
|
||||
minuteDataSplit := strutil.SplitEx(strutil.ReplaceWithMap(item.(string), map[string]string{
|
||||
"\r\n": " ",
|
||||
}), " ", true)
|
||||
price, _ := convertor.ToFloat(minuteDataSplit[1])
|
||||
volume, _ := convertor.ToFloat(minuteDataSplit[2])
|
||||
amount := float64(0)
|
||||
if len(minuteDataSplit) >= 4 {
|
||||
amount, _ = convertor.ToFloat(minuteDataSplit[3])
|
||||
}
|
||||
minuteData := &MinuteData{
|
||||
Time: minuteDataSplit[0][0:2] + ":" + minuteDataSplit[0][2:4],
|
||||
Price: price,
|
||||
Volume: volume,
|
||||
Amount: amount,
|
||||
}
|
||||
*minuteDatas = append(*minuteDatas, *minuteData)
|
||||
}
|
||||
date = m2["date"].(string)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return minuteDatas, date
|
||||
}
|
||||
|
||||
func (receiver StockDataApi) GetKLineData(stockCode string, kLineType string, days int64) *[]KLineData {
|
||||
url := fmt.Sprintf("http://quotes.sina.cn/cn/api/json_v2.php/CN_MarketDataService.getKLineData?symbol=%s&scale=%s&ma=yes&datalen=%d", stockCode, kLineType, days)
|
||||
K := &[]KLineData{}
|
||||
@ -1592,3 +1652,10 @@ type KLineData struct {
|
||||
Close string `json:"close"`
|
||||
Volume string `json:"volume"`
|
||||
}
|
||||
|
||||
type MinuteData struct {
|
||||
Time string `json:"time"`
|
||||
Price float64 `json:"price"`
|
||||
Volume float64 `json:"volume"`
|
||||
Amount float64 `json:"amount"`
|
||||
}
|
||||
|
@ -70,7 +70,12 @@ func TestSearchStockPriceInfo(t *testing.T) {
|
||||
//getZSInfo("沪深300指数", "sh000300", 30)
|
||||
|
||||
}
|
||||
|
||||
func TestGetStockMinutePriceData(t *testing.T) {
|
||||
db.Init("../../data/stock.db")
|
||||
data, date := NewStockDataApi().GetStockMinutePriceData("usTSLA.OQ")
|
||||
logger.SugaredLogger.Infof("date:%s", date)
|
||||
logger.SugaredLogger.Infof("%+#v", *data)
|
||||
}
|
||||
func TestGetKLineData(t *testing.T) {
|
||||
db.Init("../../data/stock.db")
|
||||
k := NewStockDataApi().GetKLineData("sh600171", "240", 30)
|
||||
|
@ -96,7 +96,7 @@ function handleKLine(code,name){
|
||||
color: darkTheme?'#ccc':'#456'
|
||||
},
|
||||
formatter: function (params) {//修改鼠标划过显示为中文
|
||||
console.log("params",params)
|
||||
//console.log("params",params)
|
||||
let currentItemData = _.filter(params, (param) => param.seriesIndex === 0)[0].data;
|
||||
let ma5=_.filter(params, (param) => param.seriesIndex === 1)[0].data;//ma5的值
|
||||
let ma10=_.filter(params, (param) => param.seriesIndex === 2)[0].data;//ma10的值
|
||||
@ -354,6 +354,10 @@ function handleKLine(code,name){
|
||||
]
|
||||
};
|
||||
chart.setOption(option);
|
||||
|
||||
chart.on('click',{seriesName:'日K'}, function(params) {
|
||||
console.log("click:",params);
|
||||
});
|
||||
})
|
||||
}
|
||||
function calculateMA(dayCount,values) {
|
||||
|
@ -23,7 +23,7 @@ import {
|
||||
AddGroup,
|
||||
GetGroupList,
|
||||
AddStockGroup,
|
||||
RemoveStockGroup, RemoveGroup,GetStockKLine
|
||||
RemoveStockGroup, RemoveGroup, GetStockKLine, GetStockMinutePriceLineData
|
||||
} from '../../wailsjs/go/main/App'
|
||||
import {
|
||||
NAvatar,
|
||||
@ -66,6 +66,7 @@ const upBorderColor = '';
|
||||
const downColor = '#00da3c';
|
||||
const downBorderColor = '';
|
||||
const kLineChartRef = ref(null);
|
||||
const kLineChartRef2 = ref(null);
|
||||
|
||||
|
||||
const handleProgress = (progress) => {
|
||||
@ -600,6 +601,103 @@ function showFenshi(code,name){
|
||||
}
|
||||
|
||||
modalShow2.value=true
|
||||
|
||||
GetStockMinutePriceLineData(code,name).then(result => {
|
||||
console.log("GetStockMinutePriceLineData",result)
|
||||
const priceData=result.priceData
|
||||
const chart = echarts.init(kLineChartRef2.value);
|
||||
let category=[]
|
||||
let price=[]
|
||||
let volume=[]
|
||||
let min=0
|
||||
let max=0
|
||||
for (let i = 0; i < priceData.length; i++) {
|
||||
category.push(priceData[i].time)
|
||||
price.push(priceData[i].price)
|
||||
if(min===0||min>priceData[i].price){
|
||||
min=priceData[i].price
|
||||
}
|
||||
if(max<priceData[i].price){
|
||||
max=priceData[i].price
|
||||
}
|
||||
if(i>0){
|
||||
volume.push(priceData[i].volume-priceData[i-1].volume)
|
||||
}else{
|
||||
volume.push(priceData[i].volume)
|
||||
}
|
||||
}
|
||||
|
||||
let option = {
|
||||
title: {
|
||||
text: result.date,
|
||||
left: 'center',
|
||||
textStyle: {
|
||||
color: data.darkTheme?'#ccc':'#456'
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
data: ['股价', '成交量'],
|
||||
textStyle: {
|
||||
color: data.darkTheme?'#ccc':'#456'
|
||||
},
|
||||
right: 20,
|
||||
},
|
||||
darkMode: data.darkTheme,
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'cross',
|
||||
animation: false,
|
||||
label: {
|
||||
backgroundColor: '#505765'
|
||||
}
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: category
|
||||
},
|
||||
yAxis: [
|
||||
{
|
||||
name:"股价",
|
||||
min: min-1,
|
||||
max: max+1,
|
||||
minInterval:0.01,
|
||||
type: 'value'
|
||||
},
|
||||
{
|
||||
name:"成交量",
|
||||
type: 'value',
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name:"股价",
|
||||
data: price,
|
||||
type: 'line',
|
||||
smooth: false,
|
||||
showSymbol: false,
|
||||
markPoint: {
|
||||
data: [
|
||||
{ type: 'max', name: 'Max' },
|
||||
{ type: 'min', name: 'Min' }
|
||||
]
|
||||
},
|
||||
markLine: {
|
||||
data: [{ type: 'average', name: 'Avg' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
yAxisIndex: 1,
|
||||
name:"成交量",
|
||||
data: volume,
|
||||
type: 'bar',
|
||||
}
|
||||
]
|
||||
};
|
||||
chart.setOption(option);
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
function calculateMA(dayCount,values) {
|
||||
@ -670,7 +768,7 @@ function handleKLine(){
|
||||
color: data.darkTheme?'#ccc':'#456'
|
||||
},
|
||||
formatter: function (params) {//修改鼠标划过显示为中文
|
||||
console.log("params",params)
|
||||
//console.log("params",params)
|
||||
let volum=params[5].data;//ma5的值
|
||||
let ma5=params[1].data;//ma5的值
|
||||
let ma10=params[2].data;//ma10的值
|
||||
@ -937,6 +1035,9 @@ function handleKLine(){
|
||||
]
|
||||
};
|
||||
chart.setOption(option);
|
||||
chart.on('click',{seriesName:'日K'}, function(params) {
|
||||
console.log("click:",params);
|
||||
});
|
||||
})
|
||||
}
|
||||
function showK(code,name){
|
||||
@ -1534,8 +1635,9 @@ function delStockGroup(code,name,groupId){
|
||||
</n-flex>
|
||||
</template>
|
||||
</n-modal>
|
||||
<n-modal v-model:show="modalShow2" :title="data.name" style="width: 600px" :preset="'card'">
|
||||
<n-image :src="data.fenshiURL" />
|
||||
<n-modal v-model:show="modalShow2" :title="data.name" style="width: 900px" :preset="'card'">
|
||||
<!-- <n-image :src="data.fenshiURL" />-->
|
||||
<div ref="kLineChartRef2" style="width: 850px; height: 500px;"></div>
|
||||
</n-modal>
|
||||
<n-modal v-model:show="modalShow3" :title="data.name" style="width: 900px" :preset="'card'" @after-enter="handleKLine">
|
||||
<!-- <n-image :src="data.kURL" />-->
|
||||
|
2
frontend/wailsjs/go/main/App.d.ts
vendored
2
frontend/wailsjs/go/main/App.d.ts
vendored
@ -41,6 +41,8 @@ export function GetStockKLine(arg1:string,arg2:string,arg3:number):Promise<any>;
|
||||
|
||||
export function GetStockList(arg1:string):Promise<Array<data.StockBasic>>;
|
||||
|
||||
export function GetStockMinutePriceLineData(arg1:string,arg2:string):Promise<Record<string, any>>;
|
||||
|
||||
export function GetTelegraphList(arg1:string):Promise<any>;
|
||||
|
||||
export function GetVersionInfo():Promise<models.VersionInfo>;
|
||||
|
@ -78,6 +78,10 @@ export function GetStockList(arg1) {
|
||||
return window['go']['main']['App']['GetStockList'](arg1);
|
||||
}
|
||||
|
||||
export function GetStockMinutePriceLineData(arg1, arg2) {
|
||||
return window['go']['main']['App']['GetStockMinutePriceLineData'](arg1, arg2);
|
||||
}
|
||||
|
||||
export function GetTelegraphList(arg1) {
|
||||
return window['go']['main']['App']['GetTelegraphList'](arg1);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user