• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

Go编写一个比特币交易自动出价程序

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

语言环境为>=go1.10

go语言环境不多说

实现目的能与BitMEX api进行交互自动交易,目前虚拟币平台很多,平台API实现也很容易.后续会加上其它平台和自动交易算法策略,具体看平台交易手续费性价比而定.

先从国内平台开始,以GO语言为例子,其他语言也有很多,主要是学习GO语言.

这里需要用到websocket,当然还有其他形式的请求API,这里以这种形式为例子,

先从火币开始,如果不知道API具体参数可查看官网.

先在我的GOPATH中的SRC目录中创建一个文件夹,为huobi,在这个文件夹中创建一个主程序main.go,单纯请求火币获取行情参数.

websocket使用第三方包使用,github.com/gorilla/websocket,比官方的net包多些功能.引入后创建类型拨号器,然后拨号

这是拨号器结构体,拨号器包含连接websocket的选项

type Dialer struct {
    // NetDial specifies the dial function for creating TCP connections. If
    // NetDial is nil, net.Dial is used.
    NetDial func(network, addr string) (net.Conn, error)

    // Proxy specifies a function to return a proxy for a given
    // Request. If the function returns a non-nil error, the
    // request is aborted with the provided error.
    // If Proxy is nil or returns a nil *URL, no proxy is used.
    Proxy func(*http.Request) (*url.URL, error)

    // TLSClientConfig specifies the TLS configuration to use with tls.Client.
    // If nil, the default configuration is used.
    TLSClientConfig *tls.Config

    // HandshakeTimeout specifies the duration for the handshake to complete.
    HandshakeTimeout time.Duration

    // ReadBufferSize and WriteBufferSize specify I/O buffer sizes. If a buffer
    // size is zero, then a useful default size is used. The I/O buffer sizes
    // do not limit the size of the messages that can be sent or received.
    ReadBufferSize, WriteBufferSize int

    // Subprotocols specifies the client\'s requested subprotocols.
    Subprotocols []string

    // EnableCompression specifies if the client should attempt to negotiate
    // per message compression (RFC 7692). Setting this value to true does not
    // guarantee that compression will be supported. Currently only "no context
    // takeover" modes are supported.
    EnableCompression bool

    // Jar specifies the cookie jar.
    // If Jar is nil, cookies are not sent in requests and ignored
    // in responses.
    Jar http.CookieJar
}

根据需求创建好后拨号,包含字符串很请求协议,协议一般为nil

func (d *Dialer) Dial(urlStr string, requestHeader http.Header) (*Conn, *http.Response, error)

 接下来进入API规则部分,对应火币,

完整代码

package main

import (
    "fmt"
    "time"
    "strconv"         //字符串转换
    "encoding/json"          //JSON包
    "github.com/gorilla/websocket"   //go的websocket实现
    "huobi/common"
    "huobi/conf"
)

func main()  {
    dialer := websocket.Dialer{/*根据需要设置字段*/}   //类型拨号器
    ws, _, err := dialer.Dial("wss://api.huobi.pro/ws", nil)  //拨号,返回连接对象,响应和错误
    if err != nil {
    	// handle error
    }

    for {        //因为是websocket,所以是不停的
        if _,p,err := ws.ReadMessage();err == nil {  //读取信息,这里是火币的规则
            res := common.UnGzip(p)            //解压数据
            fmt.Println(string(res))           //输出字符串
            resMap := common.JsonDecodeByte(res)   //JSON解码
            if  v, ok := resMap["ping"];ok  {
                pingMap := make(map[string]interface{})
                pingMap["pong"] = v            //发送pong包,完成ping,pong
                pingParams := common.JsonEncodeMapToByte(pingMap)  //转成JSON
                if err := ws.WriteMessage(websocket.TextMessage, pingParams); err == nil {  //发送消息,TextMessage是整型,整数常量来标识两种数据消息类型
                    reqMap := new(common.ReqStruct)//创建结构体指针
                    reqMap.Id = strconv.Itoa(time.Now().Nanosecond())
                    reqMap.Req = conf.LtcTopic.KLineTopicDesc
                    reqBytes , err := json.Marshal(reqMap)
                    if err!=nil {
                        continue
                    }
                    if err := ws.WriteMessage(websocket.TextMessage,reqBytes); err == nil {  //发送ID REQ
                    }else{
                        fmt.Errorf("send req response error %s",err.Error())
                    }
                }else{
                    fmt.Errorf("huobi server ping client error %s",err.Error())
                    continue
                }
            }
            if  _, ok := resMap["rep"];ok  {
                var resStruct common.ResStruct
                json.Unmarshal(res,&resStruct)
                //resStruct.Status
                fmt.Println(resStruct)//输出内容
            }
        }
    }
}

如果无法访问还需设置代理

dialer := websocket.Dialer{Proxy:func(*http.Request) (*url.URL, error) {
        return url.Parse("http://127.0.0.1:1080")
        },  //类型拨号器
}

流程:

1.火币的API数据都是gzip压缩过的,所以一开始连接API接收数据需要把数据进行解压

2.解压完输出内容,输出完进行JSON的解析,然后把PING对应的值取出赋值给PING发送回去,这是火币心跳包检测,两次没发回去则断开连接

3.然后请求需要获取的币种格式,market.$symbol.kline.$period对应

"req": "market.btcusdt.kline.1min",
  "id": "id10"
4.这是请求数据,然后会得到反馈

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Go语言之进阶篇服务器如何知道用户需要什么资源发布时间:2022-07-10
下一篇:
[Go] 正则表达式 示例发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap