Compare commits
7 Commits
v2026.01.0
...
v2026.01.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d1e437b47 | ||
|
|
eca2f8adee | ||
|
|
49d2109d60 | ||
|
|
f9294fbffd | ||
|
|
cc12a886c1 | ||
|
|
34ea989d47 | ||
|
|
aadff1c5eb |
6
.github/workflows/main.yml
vendored
6
.github/workflows/main.yml
vendored
@@ -29,6 +29,12 @@ jobs:
|
||||
- name: 'go-stock-darwin-universal'
|
||||
platform: 'darwin/universal'
|
||||
os: 'macos-latest'
|
||||
- name: 'go-stock-darwin-intel'
|
||||
platform: 'darwin'
|
||||
os: 'macos-latest'
|
||||
- name: 'go-stock-darwin-arm64'
|
||||
platform: 'darwin/arm64'
|
||||
os: 'macos-latest'
|
||||
|
||||
runs-on: ${{ matrix.build.os }}
|
||||
steps:
|
||||
|
||||
73
app.go
73
app.go
@@ -70,8 +70,10 @@ func AddTools(tools []data.Tool) []data.Tool {
|
||||
"words": map[string]any{
|
||||
"type": "string",
|
||||
"description": "选股自然语言。" +
|
||||
"例如,查看技术指标:上海贝岭,macd,rsi,kdj,boll,5日均线,14日均线,30日均线,60日均线,成交量,OBV,EMA" +
|
||||
"例如,查看有潜力的成交量爆发股:最近7日成交量量比大于3,出现过一次,非ST" +
|
||||
"例如:查看技术指标:上海贝岭,macd,rsi,kdj,boll,5日均线,14日均线,30日均线,60日均线,成交量,OBV,EMA" +
|
||||
"例如:查看近期趋势:量比连续2天>1,主力连续2日净流入且递增,主力净额>3000万元,行业,股价在20日线上" +
|
||||
"例如:当日成交量 ≥ 近 5 日平均成交量 ×1.5,收盘价 ≥ 20 日均线,20 日均线 ≥ 60 日均线,当日涨幅 3%-7%, 3日主力资金净流入累计≥5000 万元,当日换手率 5%-15%,筹码集中度(90% 筹码峰)≤15%,非创业板非科创板非ST非北交所,行业," +
|
||||
"例如:查看有潜力的成交量爆发股:最近7日成交量量比大于3,出现过一次,非ST" +
|
||||
"例1:创新药,半导体;PE<30;净利润增长率>50%。 " +
|
||||
"例2:上证指数,科创50。 " +
|
||||
"例3:长电科技,上海贝岭。" +
|
||||
@@ -187,6 +189,59 @@ func AddTools(tools []data.Tool) []data.Tool {
|
||||
},
|
||||
})
|
||||
|
||||
tools = append(tools, data.Tool{
|
||||
Type: "function",
|
||||
Function: data.ToolFunction{
|
||||
Name: "HotStockTable",
|
||||
Description: "当前热门股票排名",
|
||||
Parameters: &data.FunctionParameters{
|
||||
Type: "object",
|
||||
Properties: map[string]any{
|
||||
"pageSize": map[string]any{
|
||||
"type": "string",
|
||||
"description": "分页大小",
|
||||
},
|
||||
},
|
||||
Required: []string{"pageSize"},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
tools = append(tools, data.Tool{
|
||||
Type: "function",
|
||||
Function: data.ToolFunction{
|
||||
Name: "GetStockMoneyData",
|
||||
Description: "今日股票资金流入排名",
|
||||
Parameters: &data.FunctionParameters{
|
||||
Type: "object",
|
||||
Properties: map[string]any{
|
||||
"pageSize": map[string]any{
|
||||
"type": "string",
|
||||
"description": "分页大小",
|
||||
},
|
||||
},
|
||||
Required: []string{"pageSize"},
|
||||
},
|
||||
},
|
||||
})
|
||||
tools = append(tools, data.Tool{
|
||||
Type: "function",
|
||||
Function: data.ToolFunction{
|
||||
Name: "GetStockConceptInfo",
|
||||
Description: "获取股票所属概念详细信息",
|
||||
Parameters: &data.FunctionParameters{
|
||||
Type: "object",
|
||||
Properties: map[string]any{
|
||||
"code": map[string]any{
|
||||
"type": "string",
|
||||
"description": "股票代码,如:601138.SH。注意 上海证券交易所股票以.SH结尾,深圳证券交易所股票以.SZ结尾,港股股票以.HK结尾,北交所股票以.BJ结尾,",
|
||||
},
|
||||
},
|
||||
Required: []string{"code"},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
return tools
|
||||
}
|
||||
|
||||
@@ -431,7 +486,7 @@ func (a *App) syncNews() {
|
||||
}
|
||||
dataTime := time.UnixMilli(int64(news.Time * 1000))
|
||||
|
||||
if slice.ContainAny(news.Tags, []string{"外媒资讯", "财联社电报", "新浪财经"}) {
|
||||
if slice.ContainAny(news.Tags, []string{"外媒资讯", "财联社电报", "新浪财经", "外媒简讯", "外媒"}) {
|
||||
isRed := false
|
||||
if slice.Contain(news.Tags, "rotating_light") {
|
||||
isRed = true
|
||||
@@ -453,8 +508,14 @@ func (a *App) syncNews() {
|
||||
}
|
||||
if cnt == 0 {
|
||||
db.Dao.Model(telegraph).Create(&telegraph)
|
||||
a.NewsPush(&[]models.Telegraph{*telegraph})
|
||||
for _, subject := range news.Tags {
|
||||
//计算时间差如果<5分钟则推送
|
||||
if time.Now().Sub(dataTime) < 5*time.Minute {
|
||||
a.NewsPush(&[]models.Telegraph{*telegraph})
|
||||
}
|
||||
tags := slice.Filter(news.Tags, func(index int, item string) bool {
|
||||
return !(item == "rotating_light" || item == "loudspeaker")
|
||||
})
|
||||
for _, subject := range tags {
|
||||
tag := &models.Tags{
|
||||
Name: subject,
|
||||
Type: "subject",
|
||||
@@ -471,7 +532,7 @@ func (a *App) syncNews() {
|
||||
}
|
||||
|
||||
func GetSource(tags []string) string {
|
||||
if slices.Contains(tags, "外媒简讯") {
|
||||
if slice.ContainAny(tags, []string{"外媒简讯", "外媒资讯", "外媒"}) {
|
||||
return "外媒"
|
||||
}
|
||||
if slices.Contains(tags, "财联社电报") {
|
||||
|
||||
@@ -142,6 +142,8 @@ func TestXUEQIUHotStock(t *testing.T) {
|
||||
logger.SugaredLogger.Debugf("value: %+v", a)
|
||||
}
|
||||
|
||||
md := util.MarkdownTableWithTitle("当前热门股票排名", res)
|
||||
logger.SugaredLogger.Debugf(md)
|
||||
}
|
||||
|
||||
func TestHotEvent(t *testing.T) {
|
||||
@@ -235,7 +237,7 @@ func TestReutersNew(t *testing.T) {
|
||||
|
||||
func TestInteractiveAnswer(t *testing.T) {
|
||||
db.Init("../../data/stock.db")
|
||||
datas := NewMarketNewsApi().InteractiveAnswer(1, 100, "")
|
||||
datas := NewMarketNewsApi().InteractiveAnswer(1, 100, "立讯精密")
|
||||
logger.SugaredLogger.Debugf("PageSize:%d", datas.PageSize)
|
||||
md := util.MarkdownTableWithTitle("投资互动", datas.Results)
|
||||
logger.SugaredLogger.Debugf(md)
|
||||
|
||||
@@ -67,7 +67,7 @@ func NewDeepSeekOpenAi(ctx context.Context, aiConfigId int) *OpenAi {
|
||||
settingConfig.CrawlTimeOut = 60
|
||||
}
|
||||
if settingConfig.KDays < 30 {
|
||||
settingConfig.KDays = 120
|
||||
settingConfig.KDays = 60
|
||||
}
|
||||
}
|
||||
o := &OpenAi{
|
||||
@@ -193,7 +193,22 @@ func (o *OpenAi) NewSummaryStockNewsStreamWithTools(userQuestion string, sysProm
|
||||
"content": "当前本地时间是:" + time.Now().Format("2006-01-02 15:04:05"),
|
||||
})
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(5)
|
||||
wg.Add(4)
|
||||
|
||||
//go func() {
|
||||
// defer wg.Done()
|
||||
// res := NewMarketNewsApi().XUEQIUHotStock(50, "10")
|
||||
// md := util.MarkdownTableWithTitle("当前热门股票排名", res)
|
||||
// msg = append(msg, map[string]interface{}{
|
||||
// "role": "user",
|
||||
// "content": "当前热门股票排名数据",
|
||||
// })
|
||||
// msg = append(msg, map[string]interface{}{
|
||||
// "role": "assistant",
|
||||
// "reasoning_content": "使用工具查询",
|
||||
// "content": md,
|
||||
// })
|
||||
//}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
datas := NewMarketNewsApi().InteractiveAnswer(1, 100, "")
|
||||
@@ -236,30 +251,30 @@ func (o *OpenAi) NewSummaryStockNewsStreamWithTools(userQuestion string, sysProm
|
||||
})
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
var market strings.Builder
|
||||
market.WriteString(GetZSInfo("上证指数", "sh000001", 30) + "\n")
|
||||
market.WriteString(GetZSInfo("深证成指", "sz399001", 30) + "\n")
|
||||
market.WriteString(GetZSInfo("创业板指数", "sz399006", 30) + "\n")
|
||||
market.WriteString(GetZSInfo("科创50", "sh000688", 30) + "\n")
|
||||
market.WriteString(GetZSInfo("沪深300指数", "sh000300", 30) + "\n")
|
||||
market.WriteString(GetZSInfo("中证银行", "sz399986", 30) + "\n")
|
||||
market.WriteString(GetZSInfo("科创芯片", "sh000685", 30) + "\n")
|
||||
market.WriteString(GetZSInfo("上证医药", "sh000037", 30) + "\n")
|
||||
market.WriteString(GetZSInfo("证券龙头", "sz399437", 30) + "\n")
|
||||
market.WriteString(GetZSInfo("中证白酒", "sz399997", 30) + "\n")
|
||||
//logger.SugaredLogger.Infof("NewChatStream getZSInfo=\n%s", market.String())
|
||||
msg = append(msg, map[string]interface{}{
|
||||
"role": "user",
|
||||
"content": "当前市场/大盘/行业/指数行情",
|
||||
})
|
||||
msg = append(msg, map[string]interface{}{
|
||||
"role": "assistant",
|
||||
"reasoning_content": "使用工具查询",
|
||||
"content": "当前市场/大盘/行业/指数行情如下:\n" + market.String(),
|
||||
})
|
||||
}()
|
||||
//go func() {
|
||||
// defer wg.Done()
|
||||
// var market strings.Builder
|
||||
// market.WriteString(GetZSInfo("上证指数", "sh000001", 5) + "\n")
|
||||
// market.WriteString(GetZSInfo("深证成指", "sz399001", 5) + "\n")
|
||||
// market.WriteString(GetZSInfo("创业板指数", "sz399006", 5) + "\n")
|
||||
// market.WriteString(GetZSInfo("科创50", "sh000688", 5) + "\n")
|
||||
// market.WriteString(GetZSInfo("沪深300指数", "sh000300", 5) + "\n")
|
||||
// market.WriteString(GetZSInfo("中证银行", "sz399986", 5) + "\n")
|
||||
// //market.WriteString(GetZSInfo("科创芯片", "sh000685", 30) + "\n")
|
||||
// //market.WriteString(GetZSInfo("上证医药", "sh000037", 30) + "\n")
|
||||
// //market.WriteString(GetZSInfo("证券龙头", "sz399437", 30) + "\n")
|
||||
// //market.WriteString(GetZSInfo("中证白酒", "sz399997", 30) + "\n")
|
||||
// //logger.SugaredLogger.Infof("NewChatStream getZSInfo=\n%s", market.String())
|
||||
// msg = append(msg, map[string]interface{}{
|
||||
// "role": "user",
|
||||
// "content": "当前市场/大盘/行业/指数行情",
|
||||
// })
|
||||
// msg = append(msg, map[string]interface{}{
|
||||
// "role": "assistant",
|
||||
// "reasoning_content": "使用工具查询",
|
||||
// "content": "当前市场/大盘/行业/指数行情如下:\n" + market.String(),
|
||||
// })
|
||||
//}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
@@ -409,30 +424,30 @@ func (o *OpenAi) NewSummaryStockNewsStream(userQuestion string, sysPromptId *int
|
||||
"content": "当前本地时间是:" + time.Now().Format("2006-01-02 15:04:05"),
|
||||
})
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(4)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
var market strings.Builder
|
||||
market.WriteString(GetZSInfo("上证指数", "sh000001", 30) + "\n")
|
||||
market.WriteString(GetZSInfo("深证成指", "sz399001", 30) + "\n")
|
||||
market.WriteString(GetZSInfo("创业板指数", "sz399006", 30) + "\n")
|
||||
market.WriteString(GetZSInfo("科创50", "sh000688", 30) + "\n")
|
||||
market.WriteString(GetZSInfo("沪深300指数", "sh000300", 30) + "\n")
|
||||
market.WriteString(GetZSInfo("中证银行", "sz399986", 30) + "\n")
|
||||
market.WriteString(GetZSInfo("科创芯片", "sh000685", 30) + "\n")
|
||||
market.WriteString(GetZSInfo("上证医药", "sh000037", 30) + "\n")
|
||||
market.WriteString(GetZSInfo("证券龙头", "sz399437", 30) + "\n")
|
||||
market.WriteString(GetZSInfo("中证白酒", "sz399997", 30) + "\n")
|
||||
//logger.SugaredLogger.Infof("NewChatStream getZSInfo=\n%s", market.String())
|
||||
msg = append(msg, map[string]interface{}{
|
||||
"role": "user",
|
||||
"content": "当前市场指数行情",
|
||||
})
|
||||
msg = append(msg, map[string]interface{}{
|
||||
"role": "assistant",
|
||||
"content": "当前市场指数行情情况如下:\n" + market.String(),
|
||||
})
|
||||
}()
|
||||
wg.Add(3)
|
||||
//go func() {
|
||||
// defer wg.Done()
|
||||
// var market strings.Builder
|
||||
// market.WriteString(GetZSInfo("上证指数", "sh000001", 5) + "\n")
|
||||
// market.WriteString(GetZSInfo("深证成指", "sz399001", 5) + "\n")
|
||||
// market.WriteString(GetZSInfo("创业板指数", "sz399006", 5) + "\n")
|
||||
// market.WriteString(GetZSInfo("科创50", "sh000688", 5) + "\n")
|
||||
// market.WriteString(GetZSInfo("沪深300指数", "sh000300", 5) + "\n")
|
||||
// market.WriteString(GetZSInfo("中证银行", "sz399986", 5) + "\n")
|
||||
// //market.WriteString(GetZSInfo("科创芯片", "sh000685", 30) + "\n")
|
||||
// //market.WriteString(GetZSInfo("上证医药", "sh000037", 30) + "\n")
|
||||
// //market.WriteString(GetZSInfo("证券龙头", "sz399437", 30) + "\n")
|
||||
// //market.WriteString(GetZSInfo("中证白酒", "sz399997", 30) + "\n")
|
||||
// //logger.SugaredLogger.Infof("NewChatStream getZSInfo=\n%s", market.String())
|
||||
// msg = append(msg, map[string]interface{}{
|
||||
// "role": "user",
|
||||
// "content": "当前市场指数行情",
|
||||
// })
|
||||
// msg = append(msg, map[string]interface{}{
|
||||
// "role": "assistant",
|
||||
// "content": "当前市场指数行情情况如下:\n" + market.String(),
|
||||
// })
|
||||
//}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
@@ -655,21 +670,103 @@ func (o *OpenAi) NewChatStream(stock, stockCode, userQuestion string, sysPromptI
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
var market strings.Builder
|
||||
market.WriteString(GetZSInfo("创业板指数", "sz399006", 30) + "\n")
|
||||
market.WriteString(GetZSInfo("上证综合指数", "sh000001", 30) + "\n")
|
||||
market.WriteString(GetZSInfo("沪深300指数", "sh000300", 30) + "\n")
|
||||
//logger.SugaredLogger.Infof("NewChatStream getZSInfo=\n%s", market.String())
|
||||
datas := NewMarketNewsApi().InteractiveAnswer(1, 100, stock)
|
||||
content := util.MarkdownTableWithTitle("当前最新投资者互动数据", datas.Results)
|
||||
msg = append(msg, map[string]interface{}{
|
||||
"role": "user",
|
||||
"content": "市场指数",
|
||||
"content": "投资者互动数据",
|
||||
})
|
||||
msg = append(msg, map[string]interface{}{
|
||||
"role": "assistant",
|
||||
"content": "市场指数情况如下:\n" + market.String(),
|
||||
"role": "assistant",
|
||||
"reasoning_content": "使用工具查询",
|
||||
"content": content,
|
||||
})
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
var market strings.Builder
|
||||
res := NewMarketNewsApi().GetGDP()
|
||||
md := util.MarkdownTableWithTitle("国内生产总值(GDP)", res.GDPResult.Data)
|
||||
market.WriteString(md)
|
||||
res2 := NewMarketNewsApi().GetCPI()
|
||||
md2 := util.MarkdownTableWithTitle("居民消费价格指数(CPI)", res2.CPIResult.Data)
|
||||
market.WriteString(md2)
|
||||
res3 := NewMarketNewsApi().GetPPI()
|
||||
md3 := util.MarkdownTableWithTitle("工业品出厂价格指数(PPI)", res3.PPIResult.Data)
|
||||
market.WriteString(md3)
|
||||
res4 := NewMarketNewsApi().GetPMI()
|
||||
md4 := util.MarkdownTableWithTitle("采购经理人指数(PMI)", res4.PMIResult.Data)
|
||||
market.WriteString(md4)
|
||||
|
||||
msg = append(msg, map[string]interface{}{
|
||||
"role": "user",
|
||||
"content": "国内宏观经济数据",
|
||||
})
|
||||
msg = append(msg, map[string]interface{}{
|
||||
"role": "assistant",
|
||||
"reasoning_content": "使用工具查询",
|
||||
"content": "\n# 国内宏观经济数据:\n" + market.String(),
|
||||
})
|
||||
}()
|
||||
|
||||
//go func() {
|
||||
// defer wg.Done()
|
||||
// var market strings.Builder
|
||||
// market.WriteString(GetZSInfo("上证指数", "sh000001", 5) + "\n")
|
||||
// market.WriteString(GetZSInfo("深证成指", "sz399001", 5) + "\n")
|
||||
// market.WriteString(GetZSInfo("创业板指数", "sz399006", 5) + "\n")
|
||||
// market.WriteString(GetZSInfo("科创50", "sh000688", 5) + "\n")
|
||||
// market.WriteString(GetZSInfo("沪深300指数", "sh000300", 5) + "\n")
|
||||
// market.WriteString(GetZSInfo("中证银行", "sz399986", 5) + "\n")
|
||||
// //market.WriteString(GetZSInfo("科创芯片", "sh000685", 30) + "\n")
|
||||
// //market.WriteString(GetZSInfo("上证医药", "sh000037", 30) + "\n")
|
||||
// //market.WriteString(GetZSInfo("证券龙头", "sz399437", 30) + "\n")
|
||||
// //market.WriteString(GetZSInfo("中证白酒", "sz399997", 30) + "\n")
|
||||
// //logger.SugaredLogger.Infof("NewChatStream getZSInfo=\n%s", market.String())
|
||||
// msg = append(msg, map[string]interface{}{
|
||||
// "role": "user",
|
||||
// "content": "当前市场/大盘/行业/指数行情",
|
||||
// })
|
||||
// msg = append(msg, map[string]interface{}{
|
||||
// "role": "assistant",
|
||||
// "reasoning_content": "使用工具查询",
|
||||
// "content": "当前市场/大盘/行业/指数行情如下:\n" + market.String(),
|
||||
// })
|
||||
//}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
md := strings.Builder{}
|
||||
res := NewMarketNewsApi().ClsCalendar()
|
||||
for _, a := range res {
|
||||
bytes, err := json.Marshal(a)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
//logger.SugaredLogger.Debugf("value: %+v", string(bytes))
|
||||
date := gjson.Get(string(bytes), "calendar_day")
|
||||
md.WriteString("\n### 事件/会议日期:" + date.String())
|
||||
list := gjson.Get(string(bytes), "items")
|
||||
//logger.SugaredLogger.Debugf("value: %+v,list: %+v", date.String(), list)
|
||||
list.ForEach(func(key, value gjson.Result) bool {
|
||||
logger.SugaredLogger.Debugf("key: %+v,value: %+v", key.String(), gjson.Get(value.String(), "title"))
|
||||
md.WriteString("\n- " + gjson.Get(value.String(), "title").String())
|
||||
return true
|
||||
})
|
||||
}
|
||||
msg = append(msg, map[string]interface{}{
|
||||
"role": "user",
|
||||
"content": "近期重大事件/会议",
|
||||
})
|
||||
msg = append(msg, map[string]interface{}{
|
||||
"role": "assistant",
|
||||
"reasoning_content": "使用工具查询",
|
||||
"content": "近期重大事件/会议如下:\n" + md.String(),
|
||||
})
|
||||
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
//endDate := time.Now().Format("20060102")
|
||||
@@ -787,7 +884,7 @@ func (o *OpenAi) NewChatStream(stock, stockCode, userQuestion string, sysPromptI
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
messages := GetTelegraphList(o.CrawlTimeOut)
|
||||
messages := NewMarketNewsApi().GetNews24HoursList("", random.RandInt(200, 1000))
|
||||
if messages == nil || len(*messages) == 0 {
|
||||
logger.SugaredLogger.Error("获取市场资讯失败")
|
||||
//ch <- "***❗获取市场资讯失败,分析结果可能不准确***<hr>"
|
||||
@@ -795,8 +892,9 @@ func (o *OpenAi) NewChatStream(stock, stockCode, userQuestion string, sysPromptI
|
||||
return
|
||||
}
|
||||
var messageText strings.Builder
|
||||
for _, message := range *messages {
|
||||
messageText.WriteString(message + "\n")
|
||||
for _, telegraph := range *messages {
|
||||
messageText.WriteString("## " + telegraph.Time + ":" + "\n")
|
||||
messageText.WriteString("### " + telegraph.Content + "\n")
|
||||
}
|
||||
msg = append(msg, map[string]interface{}{
|
||||
"role": "user",
|
||||
@@ -806,26 +904,6 @@ func (o *OpenAi) NewChatStream(stock, stockCode, userQuestion string, sysPromptI
|
||||
"role": "assistant",
|
||||
"content": messageText.String(),
|
||||
})
|
||||
|
||||
messages = GetTopNewsList(o.CrawlTimeOut)
|
||||
if messages == nil || len(*messages) == 0 {
|
||||
logger.SugaredLogger.Error("获取新闻资讯失败")
|
||||
//ch <- "***❗获取新闻资讯失败,分析结果可能不准确***<hr>"
|
||||
//go runtime.EventsEmit(o.ctx, "warnMsg", "❗获取新闻资讯失败,分析结果可能不准确")
|
||||
return
|
||||
}
|
||||
var newsText strings.Builder
|
||||
for _, message := range *messages {
|
||||
newsText.WriteString(message + "\n")
|
||||
}
|
||||
msg = append(msg, map[string]interface{}{
|
||||
"role": "user",
|
||||
"content": "新闻资讯",
|
||||
})
|
||||
msg = append(msg, map[string]interface{}{
|
||||
"role": "assistant",
|
||||
"content": newsText.String(),
|
||||
})
|
||||
}()
|
||||
|
||||
//go func() {
|
||||
@@ -867,54 +945,8 @@ func (o *OpenAi) NewChatStream(stock, stockCode, userQuestion string, sysPromptI
|
||||
})
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
if checkIsIndexBasic(stock) {
|
||||
return
|
||||
}
|
||||
|
||||
//messages := SearchGuShiTongStockInfo(stockCode, o.CrawlTimeOut)
|
||||
//if messages == nil || len(*messages) == 0 {
|
||||
// logger.SugaredLogger.Error("获取股势通资讯失败")
|
||||
// //ch <- "***❗获取股势通资讯失败,分析结果可能不准确***<hr>"
|
||||
// //go runtime.EventsEmit(o.ctx, "warnMsg", "❗获取股势通资讯失败,分析结果可能不准确")
|
||||
// return
|
||||
//}
|
||||
//var newsText strings.Builder
|
||||
//for _, message := range *messages {
|
||||
// newsText.WriteString(message + "\n")
|
||||
//}
|
||||
//msg = append(msg, map[string]interface{}{
|
||||
// "role": "user",
|
||||
// "content": stock + "相关新闻资讯",
|
||||
//})
|
||||
//msg = append(msg, map[string]interface{}{
|
||||
// "role": "assistant",
|
||||
// "content": newsText.String(),
|
||||
//})
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
resp := NewMarketNewsApi().TradingViewNews()
|
||||
var newsText strings.Builder
|
||||
|
||||
for _, a := range *resp {
|
||||
logger.SugaredLogger.Debugf("value: %s", a.Title)
|
||||
newsText.WriteString(a.Title + "\n")
|
||||
}
|
||||
msg = append(msg, map[string]interface{}{
|
||||
"role": "user",
|
||||
"content": "外媒全球新闻资讯",
|
||||
})
|
||||
msg = append(msg, map[string]interface{}{
|
||||
"role": "assistant",
|
||||
"content": newsText.String(),
|
||||
})
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
|
||||
msg = append(msg, map[string]interface{}{
|
||||
"role": "user",
|
||||
"content": question,
|
||||
@@ -945,18 +977,28 @@ func AskAi(o *OpenAi, err error, messages []map[string]interface{}, ch chan map[
|
||||
thinking = "enabled"
|
||||
}
|
||||
client.SetTimeout(time.Duration(o.TimeOut) * time.Second)
|
||||
config := GetSettingConfig()
|
||||
if config.HttpProxyEnabled && config.HttpProxy != "" {
|
||||
client.SetProxy(config.HttpProxy)
|
||||
}
|
||||
bodyMap := map[string]interface{}{
|
||||
"model": o.Model,
|
||||
"max_tokens": o.MaxTokens,
|
||||
"temperature": o.Temperature,
|
||||
"stream": true,
|
||||
"messages": messages,
|
||||
}
|
||||
if think {
|
||||
bodyMap["thinking"] = map[string]any{
|
||||
//"type": "disabled",
|
||||
//"type": "enabled",
|
||||
"type": thinking,
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := client.R().
|
||||
SetDoNotParseResponse(true).
|
||||
SetBody(map[string]interface{}{
|
||||
"model": o.Model,
|
||||
"thinking": map[string]any{
|
||||
"type": thinking,
|
||||
},
|
||||
"max_tokens": o.MaxTokens,
|
||||
"temperature": o.Temperature,
|
||||
"stream": true,
|
||||
"messages": messages,
|
||||
}).
|
||||
SetBody(bodyMap).
|
||||
Post("/chat/completions")
|
||||
|
||||
body := resp.RawBody()
|
||||
@@ -1096,21 +1138,29 @@ func AskAiWithTools(o *OpenAi, err error, messages []map[string]interface{}, ch
|
||||
thinking = "enabled"
|
||||
}
|
||||
client.SetTimeout(time.Duration(o.TimeOut) * time.Second)
|
||||
config := GetSettingConfig()
|
||||
if config.HttpProxyEnabled && config.HttpProxy != "" {
|
||||
client.SetProxy(config.HttpProxy)
|
||||
}
|
||||
bodyMap := map[string]interface{}{
|
||||
"model": o.Model,
|
||||
"max_tokens": o.MaxTokens,
|
||||
"temperature": o.Temperature,
|
||||
"stream": true,
|
||||
"messages": messages,
|
||||
"tools": tools,
|
||||
}
|
||||
if thinkingMode {
|
||||
bodyMap["thinking"] = map[string]any{
|
||||
//"type": "disabled",
|
||||
//"type": "enabled",
|
||||
"type": thinking,
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := client.R().
|
||||
SetDoNotParseResponse(true).
|
||||
SetBody(map[string]interface{}{
|
||||
"model": o.Model,
|
||||
"thinking": map[string]any{
|
||||
//"type": "disabled",
|
||||
//"type": "enabled",
|
||||
"type": thinking,
|
||||
},
|
||||
"max_tokens": o.MaxTokens,
|
||||
"temperature": o.Temperature,
|
||||
"stream": true,
|
||||
"messages": messages,
|
||||
"tools": tools,
|
||||
}).
|
||||
SetBody(bodyMap).
|
||||
Post("/chat/completions")
|
||||
|
||||
body := resp.RawBody()
|
||||
@@ -1643,6 +1693,128 @@ func AskAiWithTools(o *OpenAi, err error, messages []map[string]interface{}, ch
|
||||
})
|
||||
}
|
||||
|
||||
if funcName == "HotStockTable" {
|
||||
pageSize := gjson.Get(funcArguments, "pageSize").String()
|
||||
ch <- map[string]any{
|
||||
"code": 1,
|
||||
"question": question,
|
||||
"chatId": streamResponse.Id,
|
||||
"model": streamResponse.Model,
|
||||
"content": "\r\n```\r\n开始调用工具:HotStockTable,\n参数:" + funcArguments + "\r\n```\r\n",
|
||||
"time": time.Now().Format(time.DateTime),
|
||||
}
|
||||
pageSizeNum, err := convertor.ToInt(pageSize)
|
||||
if err != nil {
|
||||
pageSizeNum = 50
|
||||
}
|
||||
|
||||
res := NewMarketNewsApi().XUEQIUHotStock(int(pageSizeNum), "10")
|
||||
md := util.MarkdownTableWithTitle("当前热门股票排名", res)
|
||||
logger.SugaredLogger.Infof("pageSize:%s HotStockTable:\n %s", pageSize, md)
|
||||
messages = append(messages, map[string]interface{}{
|
||||
"role": "assistant",
|
||||
"content": currentAIContent.String(),
|
||||
"reasoning_content": reasoningContentText.String(),
|
||||
"tool_calls": []map[string]any{
|
||||
{
|
||||
"id": currentCallId,
|
||||
"tool_call_id": currentCallId,
|
||||
"type": "function",
|
||||
"function": map[string]string{
|
||||
"name": funcName,
|
||||
"arguments": funcArguments,
|
||||
"parameters": funcArguments,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
messages = append(messages, map[string]interface{}{
|
||||
"role": "tool",
|
||||
"content": md,
|
||||
"tool_call_id": currentCallId,
|
||||
//"reasoning_content": reasoningContentText.String(),
|
||||
//"tool_calls": choice.Delta.ToolCalls,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
if funcName == "GetStockMoneyData" {
|
||||
ch <- map[string]any{
|
||||
"code": 1,
|
||||
"question": question,
|
||||
"chatId": streamResponse.Id,
|
||||
"model": streamResponse.Model,
|
||||
"content": "\r\n```\r\n开始调用工具:GetStockMoneyData,\n参数:" + funcArguments + "\r\n```\r\n",
|
||||
"time": time.Now().Format(time.DateTime),
|
||||
}
|
||||
res := NewStockDataApi().GetStockMoneyData()
|
||||
md := util.MarkdownTableWithTitle("今日个股资金流向Top50", res.Data.Diff)
|
||||
logger.SugaredLogger.Infof("%s", md)
|
||||
messages = append(messages, map[string]interface{}{
|
||||
"role": "assistant",
|
||||
"content": currentAIContent.String(),
|
||||
"reasoning_content": reasoningContentText.String(),
|
||||
"tool_calls": []map[string]any{
|
||||
{
|
||||
"id": currentCallId,
|
||||
"tool_call_id": currentCallId,
|
||||
"type": "function",
|
||||
"function": map[string]string{
|
||||
"name": funcName,
|
||||
"arguments": funcArguments,
|
||||
"parameters": funcArguments,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
messages = append(messages, map[string]interface{}{
|
||||
"role": "tool",
|
||||
"content": md,
|
||||
"tool_call_id": currentCallId,
|
||||
//"reasoning_content": reasoningContentText.String(),
|
||||
//"tool_calls": choice.Delta.ToolCalls,
|
||||
})
|
||||
}
|
||||
|
||||
if funcName == "GetStockConceptInfo" {
|
||||
ch <- map[string]any{
|
||||
"code": 1,
|
||||
"question": question,
|
||||
"chatId": streamResponse.Id,
|
||||
"model": streamResponse.Model,
|
||||
"content": "\r\n```\r\n开始调用工具:GetStockConceptInfo,\n参数:" + funcArguments + "\r\n```\r\n",
|
||||
"time": time.Now().Format(time.DateTime),
|
||||
}
|
||||
code := gjson.Get(funcArguments, "code").String()
|
||||
res := NewStockDataApi().GetStockConceptInfo(code)
|
||||
md := util.MarkdownTableWithTitle(code+" 股票所属概念详细信息", res.Result.Data)
|
||||
logger.SugaredLogger.Infof("%s", md)
|
||||
messages = append(messages, map[string]interface{}{
|
||||
"role": "assistant",
|
||||
"content": currentAIContent.String(),
|
||||
"reasoning_content": reasoningContentText.String(),
|
||||
"tool_calls": []map[string]any{
|
||||
{
|
||||
"id": currentCallId,
|
||||
"tool_call_id": currentCallId,
|
||||
"type": "function",
|
||||
"function": map[string]string{
|
||||
"name": funcName,
|
||||
"arguments": funcArguments,
|
||||
"parameters": funcArguments,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
messages = append(messages, map[string]interface{}{
|
||||
"role": "tool",
|
||||
"content": md,
|
||||
"tool_call_id": currentCallId,
|
||||
//"reasoning_content": reasoningContentText.String(),
|
||||
//"tool_calls": choice.Delta.ToolCalls,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
AskAiWithTools(o, err, messages, ch, question, tools, thinkingMode)
|
||||
}
|
||||
|
||||
@@ -30,9 +30,9 @@ func TestNewDeepSeekOpenAiConfig(t *testing.T) {
|
||||
},
|
||||
})
|
||||
|
||||
ai := NewDeepSeekOpenAi(context.TODO(), 0)
|
||||
ai := NewDeepSeekOpenAi(context.TODO(), 11)
|
||||
//res := ai.NewChatStream("长电科技", "sh600584", "长电科技分析和总结", nil)
|
||||
res := ai.NewSummaryStockNewsStreamWithTools("总结市场资讯,发掘潜力标的/行业/板块/概念,控制风险。调用工具函数验证", nil, tools, true)
|
||||
res := ai.NewSummaryStockNewsStreamWithTools("总结市场资讯,发掘潜力标的/行业/板块/概念,控制风险。调用工具函数验证", nil, tools, false)
|
||||
|
||||
for {
|
||||
select {
|
||||
@@ -65,6 +65,6 @@ func TestSearchGuShiTongStockInfo(t *testing.T) {
|
||||
|
||||
func TestGetZSInfo(t *testing.T) {
|
||||
db.Init("../../data/stock.db")
|
||||
GetZSInfo("中证银行", "sz399986", 30)
|
||||
GetZSInfo("上海贝岭", "sh600171", 30)
|
||||
GetZSInfo("中证银行", "sz399986", 5)
|
||||
GetZSInfo("上海贝岭", "sh600171", 5)
|
||||
}
|
||||
|
||||
@@ -97,3 +97,22 @@ func (s SearchStockApi) HotStrategyTable() string {
|
||||
markdownTable = util.MarkdownTableWithTitle("当前热门选股策略", strategy.Data)
|
||||
return markdownTable
|
||||
}
|
||||
|
||||
func (s SearchStockApi) StrategySquare() map[string]any {
|
||||
//https://backtest.10jqka.com.cn/strategysquare/list?order=desc&page=1&pageNum=10&sortType=hot&keyword=
|
||||
url := "https://backtest.10jqka.com.cn/strategysquare/list?order=desc&page=1&pageNum=10&sortType=hot&keyword="
|
||||
resp, err := resty.New().SetTimeout(time.Duration(30)*time.Second).R().
|
||||
SetHeader("Host", "backtest.10jqka.com.cn").
|
||||
SetHeader("Origin", "https://backtest.10jqka.com.cn").
|
||||
SetHeader("Referer", "https://backtest.10jqka.com.cn/strategysquare/list").
|
||||
SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0").
|
||||
Get(url)
|
||||
if err != nil {
|
||||
logger.SugaredLogger.Errorf("StrategySquare-err:%+v", err)
|
||||
return map[string]any{}
|
||||
}
|
||||
respMap := map[string]any{}
|
||||
json.Unmarshal(resp.Body(), &respMap)
|
||||
logger.SugaredLogger.Infof("resp:%+v", respMap["data"])
|
||||
return respMap
|
||||
}
|
||||
|
||||
@@ -80,3 +80,8 @@ func TestSearchStockApi_HotStrategy(t *testing.T) {
|
||||
// logger.SugaredLogger.Infof("v:%+v", d)
|
||||
//}
|
||||
}
|
||||
func TestSearchStockApi_HotStrategyTable(t *testing.T) {
|
||||
db.Init("../../data/stock.db")
|
||||
res := NewSearchStockApi("").StrategySquare()
|
||||
logger.SugaredLogger.Infof("res:%+v", res)
|
||||
}
|
||||
|
||||
@@ -198,12 +198,6 @@ func GetSettingConfig() *SettingConfig {
|
||||
aiConfigs := make([]*AIConfig, 0)
|
||||
// 处理数据库查询可能返回的空结果
|
||||
result := db.Dao.Model(&Settings{}).First(settings)
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
// 初始化默认设置并保存到数据库
|
||||
settings = &Settings{OpenAiEnable: false, CrawlTimeOut: 60}
|
||||
db.Dao.Create(settings)
|
||||
}
|
||||
|
||||
if settings.OpenAiEnable {
|
||||
// 处理AI配置查询可能出现的错误
|
||||
result = db.Dao.Model(&AIConfig{}).Find(&aiConfigs)
|
||||
@@ -220,7 +214,7 @@ func GetSettingConfig() *SettingConfig {
|
||||
settings.CrawlTimeOut = 60
|
||||
}
|
||||
if settings.KDays < 30 {
|
||||
settings.KDays = 120
|
||||
settings.KDays = 60
|
||||
}
|
||||
}
|
||||
if settings.BrowserPath == "" {
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"go-stock/backend/models"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
url2 "net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -1203,7 +1204,7 @@ func GetZSInfo(name, stockCode string, crawlTimeOut int64) string {
|
||||
price := strutil.RemoveWhiteSpace(document.Find("div#price").First().Text(), false)
|
||||
hqTime := strutil.RemoveWhiteSpace(document.Find("div#hqTime").First().Text(), false)
|
||||
|
||||
if strutil.ContainsAny(price, []string{"-", "--", ""}) {
|
||||
if strutil.ContainsAny(price, []string{"-", "--"}) {
|
||||
return "暂无数据"
|
||||
}
|
||||
|
||||
@@ -1750,6 +1751,65 @@ func (receiver StockDataApi) GetStockHistoryMoneyData() {
|
||||
|
||||
}
|
||||
|
||||
// GetStockMoneyData 获取个股资金流数据
|
||||
func (receiver StockDataApi) GetStockMoneyData() models.StockMoneyDataResp {
|
||||
var resData models.StockMoneyDataResp
|
||||
url := "https://push2.eastmoney.com/api/qt/clist/get?cb=data&fid=f62&po=1&pz=50&pn=1&np=1&fltt=2&invt=2&ut=8dec03ba335b81bf4ebdf7b29ec27d15&fs=m:0+t:6+f:!2,m:0+t:13+f:!2,m:0+t:80+f:!2,m:1+t:2+f:!2,m:1+t:23+f:!2,m:0+t:7+f:!2,m:1+t:3+f:!2&fields=f12,f14,f2,f3,f62,f184,f66,f69,f72,f75,f78,f81,f84,f87,f204,f205,f124,f1,f13,f100,f265"
|
||||
resp, err := receiver.client.SetTimeout(time.Duration(receiver.config.CrawlTimeOut)*time.Second).R().
|
||||
SetHeader("Host", "push2.eastmoney.com").
|
||||
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())
|
||||
}
|
||||
body := string(resp.Body())
|
||||
logger.SugaredLogger.Infof("resp:%s", body)
|
||||
vm := otto.New()
|
||||
vm.Run("function data(res){return res};")
|
||||
val, err := vm.Run(body)
|
||||
if err != nil {
|
||||
logger.SugaredLogger.Errorf("err:%s", err.Error())
|
||||
}
|
||||
value, err := val.Export()
|
||||
if err != nil {
|
||||
logger.SugaredLogger.Errorf("err:%s", err.Error())
|
||||
}
|
||||
marshal, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
logger.SugaredLogger.Errorf("err:%s", err.Error())
|
||||
return models.StockMoneyDataResp{}
|
||||
}
|
||||
err = json.Unmarshal(marshal, &resData)
|
||||
if err != nil {
|
||||
logger.SugaredLogger.Errorf("err:%s", err.Error())
|
||||
return models.StockMoneyDataResp{}
|
||||
}
|
||||
return resData
|
||||
}
|
||||
|
||||
// 获取股票概念题材信息
|
||||
func (receiver StockDataApi) GetStockConceptInfo(stockCode string) models.StockConceptInfoResp {
|
||||
//601138.SH
|
||||
url := "https://datacenter.eastmoney.com/securities/api/data/v1/get?reportName=RPT_F10_CORETHEME_BOARDTYPE&columns=SECUCODE%2CSECURITY_CODE%2CSECURITY_NAME_ABBR%2CNEW_BOARD_CODE%2CBOARD_NAME%2CSELECTED_BOARD_REASON%2CIS_PRECISE%2CBOARD_RANK%2CBOARD_YIELD%2CDERIVE_BOARD_CODE"eColumns=f3~05~NEW_BOARD_CODE~BOARD_YIELD&filter=(SECUCODE%3D%22" + stockCode + "%22)(IS_PRECISE%3D%221%22)&pageNumber=1&pageSize=&sortTypes=1&sortColumns=BOARD_RANK&source=HSF10&client=PC&v=005634233622011753"
|
||||
logger.SugaredLogger.Infof("url:%s", url2.QueryEscape(url))
|
||||
var data models.StockConceptInfoResp
|
||||
resp, err := receiver.client.SetTimeout(time.Duration(receiver.config.CrawlTimeOut)*time.Second).R().
|
||||
SetHeader("Host", "datacenter.eastmoney.com").
|
||||
SetHeader("Referer", "https://emweb.securities.eastmoney.com/").
|
||||
SetHeader("Origin", "https://emweb.securities.eastmoney.com").
|
||||
SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:148.0) Gecko/20100101 Firefox/148.0").
|
||||
Get(url)
|
||||
if err != nil {
|
||||
logger.SugaredLogger.Errorf("err:%s", err.Error())
|
||||
}
|
||||
err = json.Unmarshal(resp.Body(), &data)
|
||||
if err != nil {
|
||||
logger.SugaredLogger.Errorf("err:%s", err.Error())
|
||||
return models.StockConceptInfoResp{}
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
// JSONToMarkdownTable 将JSON数据转换为Markdown表格
|
||||
func JSONToMarkdownTable(jsonData []byte) (string, error) {
|
||||
var data []map[string]interface{}
|
||||
|
||||
@@ -283,3 +283,17 @@ func TestName(t *testing.T) {
|
||||
//}
|
||||
|
||||
}
|
||||
func TestGetStockMoneyData(t *testing.T) {
|
||||
db.Init("../../data/stock.db")
|
||||
stockDataApi := NewStockDataApi()
|
||||
res := stockDataApi.GetStockMoneyData()
|
||||
logger.SugaredLogger.Infof("%s", util.MarkdownTableWithTitle("今日个股资金流向Top50", res.Data.Diff))
|
||||
}
|
||||
|
||||
func TestGetStockConceptInfo(t *testing.T) {
|
||||
db.Init("../../data/stock.db")
|
||||
stockDataApi := NewStockDataApi()
|
||||
res := stockDataApi.GetStockConceptInfo("601138.SH")
|
||||
logger.SugaredLogger.Infof("%s", util.MarkdownTableWithTitle("601138.SH所属概念/板块信息", res.Result.Data))
|
||||
|
||||
}
|
||||
|
||||
@@ -359,29 +359,29 @@ type XUEQIUHot struct {
|
||||
}
|
||||
|
||||
type HotItem struct {
|
||||
Type int `json:"type"`
|
||||
Code string `json:"code"`
|
||||
Name string `json:"name"`
|
||||
Value float64 `json:"value"`
|
||||
Increment int `json:"increment"`
|
||||
RankChange int `json:"rank_change"`
|
||||
HasExist interface{} `json:"has_exist"`
|
||||
Symbol string `json:"symbol"`
|
||||
Percent float64 `json:"percent"`
|
||||
Current float64 `json:"current"`
|
||||
Chg float64 `json:"chg"`
|
||||
Exchange string `json:"exchange"`
|
||||
StockType int `json:"stock_type"`
|
||||
SubType string `json:"sub_type"`
|
||||
Ad int `json:"ad"`
|
||||
AdId interface{} `json:"ad_id"`
|
||||
ContentId interface{} `json:"content_id"`
|
||||
Page interface{} `json:"page"`
|
||||
Model interface{} `json:"model"`
|
||||
Location interface{} `json:"location"`
|
||||
TradeSession interface{} `json:"trade_session"`
|
||||
CurrentExt interface{} `json:"current_ext"`
|
||||
PercentExt interface{} `json:"percent_ext"`
|
||||
Type int `json:"type" md:"-"`
|
||||
Code string `json:"code" md:"股票代码"`
|
||||
Name string `json:"name" md:"股票名称"`
|
||||
Value float64 `json:"value" md:"热度"`
|
||||
Increment int `json:"increment" md:"热度变化"`
|
||||
RankChange int `json:"rank_change" md:"排名变化"`
|
||||
HasExist interface{} `json:"has_exist" md:"-"`
|
||||
Symbol string `json:"symbol" md:"-"`
|
||||
Percent float64 `json:"percent" md:"涨跌幅(%)"`
|
||||
Current float64 `json:"current" md:"股价"`
|
||||
Chg float64 `json:"chg" md:"股价变化"`
|
||||
Exchange string `json:"exchange" md:"交易所代码"`
|
||||
StockType int `json:"stock_type" md:"-"`
|
||||
SubType string `json:"sub_type" md:"-"`
|
||||
Ad int `json:"ad" md:"-"`
|
||||
AdId interface{} `json:"ad_id" md:"-"`
|
||||
ContentId interface{} `json:"content_id" md:"-"`
|
||||
Page interface{} `json:"page" md:"-"`
|
||||
Model interface{} `json:"model" md:"-"`
|
||||
Location interface{} `json:"location" md:"-"`
|
||||
TradeSession interface{} `json:"trade_session" md:"-"`
|
||||
CurrentExt interface{} `json:"current_ext" md:"-"`
|
||||
PercentExt interface{} `json:"percent_ext" md:"-"`
|
||||
}
|
||||
|
||||
type HotEvent struct {
|
||||
@@ -779,3 +779,100 @@ type NtfyNews struct {
|
||||
Tags []string `json:"tags"`
|
||||
Icon string `json:"icon"`
|
||||
}
|
||||
|
||||
type THSHotStrategy struct {
|
||||
Result struct {
|
||||
Num int `json:"num"`
|
||||
List []struct {
|
||||
Author struct {
|
||||
Avatar string `json:"avatar"`
|
||||
UserName string `json:"userName"`
|
||||
UserId int `json:"userId"`
|
||||
} `json:"author"`
|
||||
Property struct {
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Query string `json:"query"`
|
||||
Logic string `json:"logic"`
|
||||
BuyPosition interface{} `json:"buyPosition"`
|
||||
Ctime string `json:"ctime"`
|
||||
Tags []string `json:"tags"`
|
||||
WinRate string `json:"winRate"`
|
||||
AnnualYield string `json:"annualYield"`
|
||||
Type int `json:"type"`
|
||||
} `json:"property"`
|
||||
Interaction struct {
|
||||
CommentNum int `json:"commentNum"`
|
||||
CollectNum int `json:"collectNum"`
|
||||
IsCollected bool `json:"isCollected"`
|
||||
IsSubscribe int `json:"isSubscribe"`
|
||||
IsPublish int `json:"isPublish"`
|
||||
Pid int `json:"pid"`
|
||||
} `json:"interaction"`
|
||||
} `json:"list"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
type StockMoneyDataResp struct {
|
||||
Rc int `json:"rc"`
|
||||
Rt int `json:"rt"`
|
||||
Svr int `json:"svr"`
|
||||
Lt int `json:"lt"`
|
||||
Full int `json:"full"`
|
||||
Dlmkts string `json:"dlmkts"`
|
||||
Data StockMoneyData `json:"data"`
|
||||
}
|
||||
|
||||
type StockMoneyData struct {
|
||||
Total int `json:"total"`
|
||||
Diff []StockMoneyDataDiff `json:"diff"`
|
||||
}
|
||||
|
||||
type StockMoneyDataDiff struct {
|
||||
F1 int `json:"f1" md:"-"`
|
||||
F12 string `json:"f12" md:"股票代码"`
|
||||
F13 int `json:"f13" md:"-"`
|
||||
F14 string `json:"f14" md:"股票名称"`
|
||||
F2 float64 `json:"f2" md:"最新价"`
|
||||
F3 float64 `json:"f3" md:"今日涨跌幅(%)"`
|
||||
F62 float64 `json:"f62" md:"今日主力净额(元)"`
|
||||
F184 float64 `json:"f184" md:"今日主力净占比(%)"`
|
||||
F66 float64 `json:"f66" md:"今日超大单净额(元)"`
|
||||
F69 float64 `json:"f69" md:"今日超大单净占比(%)"`
|
||||
F72 float64 `json:"f72" md:"今日大单净额(元)"`
|
||||
F75 float64 `json:"f75" md:"今日大单净占比(%)"`
|
||||
F78 float64 `json:"f78" md:"今日中单净额(元)"`
|
||||
F81 float64 `json:"f81" md:"今日中单净占比(%)"`
|
||||
F84 float64 `json:"f84" md:"今日小单净额(元)"`
|
||||
F87 float64 `json:"f87" md:"今日小单净占比(%)"`
|
||||
F124 int `json:"f124" md:"f124"`
|
||||
F100 string `json:"f100" md:"所属板块"`
|
||||
F265 string `json:"f265" md:"板块代码"`
|
||||
}
|
||||
|
||||
type StockConceptInfoResp struct {
|
||||
Version string `json:"version"`
|
||||
Result StockConceptInfoResult `json:"result"`
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
Code int `json:"code"`
|
||||
}
|
||||
|
||||
type StockConceptInfoResult struct {
|
||||
Pages int `json:"pages"`
|
||||
Data []StockConceptInfo `json:"data"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
type StockConceptInfo struct {
|
||||
SECUCODE string `json:"SECUCODE" md:"完整股票代码"`
|
||||
SECURITYCODE string `json:"SECURITY_CODE" md:"股票代码"`
|
||||
SECURITYNAMEABBR string `json:"SECURITY_NAME_ABBR" md:"股票名称"`
|
||||
NEWBOARDCODE string `json:"NEW_BOARD_CODE" md:"板块/概念代码"`
|
||||
BOARDNAME string `json:"BOARD_NAME" md:"板块/概念名称"`
|
||||
SELECTEDBOARDREASON string `json:"SELECTED_BOARD_REASON" md:"板块/概念描述"`
|
||||
ISPRECISE string `json:"IS_PRECISE" md:"-"`
|
||||
BOARDRANK int `json:"BOARD_RANK" md:"-"`
|
||||
BOARDYIELD float64 `json:"BOARD_YIELD" md:"板块/概念涨跌幅(%)"`
|
||||
DERIVEBOARDCODE string `json:"DERIVE_BOARD_CODE" md:"-"`
|
||||
}
|
||||
|
||||
@@ -388,7 +388,7 @@ function deletePrompt(ID) {
|
||||
</n-form-item-gi>
|
||||
<n-form-item-gi :span="4" v-if="formValue.openAI.enable" title="天数越多消耗tokens越多"
|
||||
label="日K线数据(天)" path="openAI.kDays">
|
||||
<n-input-number min="30" step="1" max="365" v-model:value="formValue.openAI.kDays"/>
|
||||
<n-input-number min="30" step="1" max="60" v-model:value="formValue.openAI.kDays"/>
|
||||
</n-form-item-gi>
|
||||
<n-form-item-gi :span="2" label="http代理" path="httpProxyEnabled">
|
||||
<n-switch v-model:value="formValue.httpProxyEnabled"/>
|
||||
|
||||
Reference in New Issue
Block a user