沪深websocket level2/level1行情推送接入示例

embedded/2024/9/23 10:20:45/

行情接入包

golang packge:

package hangqingimport ("bufio""bytes""compress/flate""encoding/json""github.com/gorilla/websocket""io/ioutil""log""net/http""net/url""strings""sync""time"
)type ServerAddrRsp struct {Code   string `json:"code"`Server string `json:"server"`
}type Hq struct {token    string          //jvQuant Tokenserver   string          //websocket服务器地址conn     *websocket.Conn //websocket连接cmdChan  chan stringexitChan chan intlv1Deal  func(string string) //level1行情处理方法lv2Deal  func(string string) //level2行情处理方法wg       *sync.WaitGroup
}//实例初始化
func (hq *Hq) Construct(token, serAddr string, lv1Handle, lv2Handle func(string string)) {hq.token = tokenif serAddr == "" {hq.server = hq.initServer()}hq.lv1Deal = lv1Handlehq.lv2Deal = lv2Handlehq.conn = hq.connect()hq.wg = &sync.WaitGroup{}hq.cmdChan = make(chan string, 128)hq.exitChan = make(chan int)//接收协程hq.wg.Add(2)go func() {hq.receive()hq.wg.Done()}()//发送协程go func() {hq.cmd()hq.wg.Done()}()
}//获取行情服务器地址
func (hq *Hq) initServer() (server string) {params := url.Values{"market": []string{"ab"},"type":   []string{"websocket"},"token":  []string{hq.token},}req := "http://jvquant.com/query/server?" + params.Encode()rb, err := HttpOnce(req, nil, nil, 3000)if err != nil {log.Fatalln("获取行情服务器地址失败:", req, err)}rspMap := ServerAddrRsp{}err = json.Unmarshal(rb, &rspMap)if err != nil {log.Fatalln("解析行情服务器地址失败:", string(rb), err)}server = rspMap.Serverif rspMap.Code != "0" || server == "" {log.Fatalln("解析行情服务器地址失败:", string(rb))}log.Println("获取行情服务器地址成功:", server)return
}//连接行情服务器
func (hq Hq) connect() (conn *websocket.Conn) {wsUrl := hq.server + "?token=" + hq.tokenconn, _, err := websocket.DefaultDialer.Dial(wsUrl, nil)if err != nil {log.Fatalln("行情服务器连接错误:", err)}return
}//增加level1行情订阅
func (hq Hq) AddLv1(codeArr []string) {cmd := "add="cmdArr := []string{}for _, code := range codeArr {cmdArr = append(cmdArr, "lv1_"+code)}cmd = cmd + strings.Join(cmdArr, ",")hq.SendRawCmd(cmd)
}//增加level2行情订阅
func (hq Hq) AddLv2(codeArr []string) {cmd := "add="cmdArr := []string{}for _, code := range codeArr {cmdArr = append(cmdArr, "lv2_"+code)}cmd = cmd + strings.Join(cmdArr, ",")hq.SendRawCmd(cmd)
}//指令入队列
func (hq Hq) SendRawCmd(cmd string) {hq.cmdChan <- cmd
}//关闭行情连接
func (hq Hq) Close() {close(hq.cmdChan)hq.exitChan <- 1hq.conn.Close()
}//线程阻塞等待
func (hq Hq) Wait() {hq.wg.Wait()
}//websocket指令发送
func (hq Hq) cmd() {for cmd := range hq.cmdChan {log.Println("发送指令:" + cmd)err := hq.conn.WriteMessage(websocket.TextMessage, []byte(cmd))if err != nil {log.Println("指令发送错误:", err)}}
}//websocket行情接收处理
func (hq Hq) receive() {for {select {case <-hq.exitChan:log.Print("接收协程退出")returndefault://阻塞接收messageType, rb, err := hq.conn.ReadMessage()if err != nil {log.Print("接收错误:", err)}//文本消息if messageType == websocket.TextMessage {log.Println("Text响应:", string(rb))}//二进制消息if messageType == websocket.BinaryMessage {unZipByte := DeCompress(rb)text := string(unZipByte)ex1 := strings.Split(text, "\n")for _, ex1r := range ex1 {ex2 := strings.Split(ex1r, "=")if len(ex2) == 2 {code := ex2[0]hqs := ex2[1]if strings.HasPrefix(code, "lv1_") {hq.lv1Deal(hqs)}if strings.HasPrefix(code, "lv2_") {hq.lv2Deal(hqs)}}}}}}
}//二进制数据解压方法
func DeCompress(b []byte) []byte {var buffer bytes.Bufferbuffer.Write([]byte(b))reader := flate.NewReader(&buffer)var result bytes.Bufferresult.ReadFrom(reader)reader.Close()return result.Bytes()
}
//http请求封装
func HttpOnce(Url string, headers, postData map[string]string, msTimeOut int) (r []byte, err error) {client := &http.Client{Timeout: time.Duration(time.Duration(msTimeOut) * time.Millisecond),}method := http.MethodGetr = []byte{}err = nilif len(headers) == 0 {headers = map[string]string{}}if len(postData) != 0 {method = http.MethodPostheaders["Content-Type"] = "application/x-www-form-urlencoded"}postParam := url.Values{}for k, v := range postData {postParam.Set(k, v)}postParamBuff := bytes.NewBufferString(postParam.Encode())req, err := http.NewRequest(method, Url, postParamBuff)if err != nil {return r, err}for k, v := range headers {req.Header.Add(k, v)}resp, er := client.Do(req)if er != nil {err = erreturn}defer resp.Body.Close()if err != nil {return r, err}br := bufio.NewReader(resp.Body)r, err = ioutil.ReadAll(br)return r, err
}

参考地址:https://github.com/jvQuant/OpenAPIDemo


http://www.ppmy.cn/embedded/26968.html

相关文章

Flutter笔记:Widgets Easier组件库(1)使用各式边框

Flutter笔记 Widgets Easier组件库&#xff08;1&#xff09;&#xff1a;使用边框 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress o…

LangChain入门2 RAG详解

RAG概述 一个典型的RAG应用程序,它有两个主要组件&#xff1a; 索引&#xff1a;从源中获取数据并对其进行索引的管道。这通常在脱机情况下发生。检索和生成&#xff1a;在运行时接受用户查询&#xff0c;并从索引中检索相关数据&#xff0c;然后将其传递给模型。 从原始数据…

Stable Diffusion教程:额外功能/后期处理/高清化

"额外功能"对应的英文单词是Extras&#xff0c;算是直译。但是部分版本中的翻译是“后期处理”或者“高清化”&#xff0c;这都是意译&#xff0c;因为它的主要功能是放大图片、去噪、修脸等对图片的后期处理。注意这里边对图片的处理不是 Stable Diffusion 本身的能…

设计模式 基本认识

文章目录 设计模式的作用设计模式三原则设计模式与类图设计模式的分类 设计模式的作用 设计模式是在软件设计过程中针对常见问题的解决方案的一种通用、可重用的解决方案。设计模式提供了一种经过验证的方法&#xff0c;可以帮助开发人员解决特定类型的问题&#xff0c;并在软…

OpenCV C++实现区域面积筛选以及统计区域个数

目录 1、背景介绍 2、代码实现 2.1 获取原图 2.1.1 区域图像imread 2.1.2 具体实现 2.2 获取图像大小 2.3 阈值分割 2.3.1 阈值分割threshold 2.3.2 具体实现 2.4 区域面积筛选 2.4.1 获取轮廓findContours 2.4.2 获取轮廓面积contourArea 2.4.3 填充区域fil…

Ollama+Open WebUI部署大模型在linux平台

Ollama安装运行 Ollama容器拉取 docker pull ollama/ollamaOllama容器CPU运行 docker run -d --restartalways -v /home/docker/ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollamaOllama容器GPU运行 # nvidia-container-runtime-script.shsudo curl -s -L …

Pytorch分布式train——pytorch.distributed.launch V.S. torchrun

1. 较早的pytorch.distributed.launch python -m torch.distributed.launch --nproc_per_node4 --nnodes1 --node_rank0 train.py --args XXX 参数解析&#xff1a; nnodes&#xff1a;节点&#xff08;主机&#xff09;的数量&#xff0c;通常一个节点对应一个主机 node_rank…

PHP源码_在线艺术字体在线生成转换设计网站源码

最全的字体转换器在线转换、艺术字体在线生成器和字体下载&#xff0c;包括书法字体在线转换、毛笔字在线生成器&#xff0c;更有草书字体、篆体字、连笔字、POP字体转换器等中文和英文字体。 支持自己添加字体&#xff0c;在线艺术字体转换器&#xff0c;织梦内核艺术字体在线…