feat(stock):支持港股和美股的K线数据获取

- 修改了 openai_api.go 中的股票代码处理逻辑,增加了对港股和美股的支持
- 新增了 StockDataApi 类中的 GetHK_KLineData 方法,用于获取港股和美股的 K 线数据
- 更新了前端 stock.vue 组件的样式
-增加了 GetHK_KLineData 方法的单元测试
This commit is contained in:
ArvinLovegood 2025-04-21 18:39:20 +08:00
parent c7d728e613
commit db3594af77
4 changed files with 75 additions and 3 deletions

View File

@ -219,8 +219,16 @@ func (o OpenAi) NewChatStream(stock, stockCode, userQuestion string, sysPromptId
// })
//}
if strutil.HasPrefixAny(stockCode, []string{"sz", "sh"}) {
K := NewStockDataApi().GetKLineData(stockCode, "240", o.KDays)
logger.SugaredLogger.Infof("NewChatStream getKLineData stock:%s stockCode:%s", stock, stockCode)
if strutil.HasPrefixAny(stockCode, []string{"sz", "sh", "hk", "us", "gb_"}) {
K := &[]KLineData{}
logger.SugaredLogger.Infof("NewChatStream getKLineData stock:%s stockCode:%s", stock, stockCode)
if strutil.HasPrefixAny(stockCode, []string{"sz", "sh"}) {
K = NewStockDataApi().GetKLineData(stockCode, "240", o.KDays)
}
if strutil.HasPrefixAny(stockCode, []string{"hk", "us", "gb_"}) {
K = NewStockDataApi().GetHK_KLineData(stockCode, "day", o.KDays)
}
Kmap := &[]map[string]any{}
for _, kline := range *K {
mapk := make(map[string]any, 6)

View File

@ -1105,6 +1105,59 @@ func (receiver StockDataApi) GetKLineData(stockCode string, kLineType string, da
}
return K
}
func (receiver StockDataApi) GetHK_KLineData(stockCode string, kLineType string, days int64) *[]KLineData {
logger.SugaredLogger.Infof("GetHK_KLineData stockCode:%s,kLineType:%s,days:%d", stockCode, kLineType, days)
if strutil.HasPrefixAny(stockCode, []string{"gb_", "GB_"}) {
stockCode = strings.Replace(stockCode, "gb_", "us", 1) + ".OQ"
}
url := fmt.Sprintf("https://web.ifzq.gtimg.cn/appstock/app/fqkline/get?param=%s,%s,,,%d,qfq", stockCode, kLineType, days)
logger.SugaredLogger.Infof("url:%s", url)
K := &[]KLineData{}
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)
if err != nil {
logger.SugaredLogger.Errorf("err:%s", err.Error())
return K
}
//logger.SugaredLogger.Infof("resp:%s", resp.Body())
json.Unmarshal(resp.Body(), &res)
code, _ := convertor.ToInt(res["code"])
if code != 0 {
return K
}
if res["data"] != nil && code == 0 {
data := res["data"].(map[string]interface{})[stockCode].(map[string]interface{})
if data != nil {
var day []any
if data["qfqday"] != nil {
day = data["qfqday"].([]any)
}
if data["day"] != nil {
day = data["day"].([]any)
}
for _, v := range day {
if v != nil {
vv := v.([]any)
KLine := &KLineData{
Day: convertor.ToString(vv[0]),
Open: convertor.ToString(vv[1]),
Close: convertor.ToString(vv[2]),
High: convertor.ToString(vv[3]),
Low: convertor.ToString(vv[4]),
Volume: convertor.ToString(vv[5]),
}
*K = append(*K, *KLine)
}
}
}
}
return K
}
// JSONToMarkdownTable 将JSON数据转换为Markdown表格
func JSONToMarkdownTable(jsonData []byte) (string, error) {

View File

@ -74,6 +74,17 @@ func TestGetKLineData(t *testing.T) {
}
logger.SugaredLogger.Infof("markdownTable:\n%s", markdownTable)
}
func TestGetHK_KLineData(t *testing.T) {
db.Init("../../data/stock.db")
k := NewStockDataApi().GetHK_KLineData("sh600171", "day", 30)
jsonData, _ := json.Marshal(*k)
markdownTable, err := JSONToMarkdownTable(jsonData)
if err != nil {
logger.SugaredLogger.Errorf("json.Marshal error:%s", err.Error())
}
logger.SugaredLogger.Infof("markdownTable:\n%s", markdownTable)
}
func TestGetRealTimeStockPriceInfo(t *testing.T) {

View File

@ -959,7 +959,7 @@ function delStockGroup(code,name,groupId){
</n-gradient-text>
</template>
</vue-danmaku>
<n-tabs type="card" animated addable @add="addTab" @update-value="updateTab" placement="top" @close="(key)=>{delTab(key)}">
<n-tabs style="--wails-draggable:drag" type="card" animated addable @add="addTab" @update-value="updateTab" placement="top" @close="(key)=>{delTab(key)}">
<n-tab-pane name="0" tab="全部">
<n-grid :x-gap="8" :cols="3" :y-gap="8" >
<n-gi :id="result['股票代码']" v-for="result in sortedResults" style="margin-left: 2px;" >