diff --git a/client.go b/client.go index 39248f5..3c57041 100644 --- a/client.go +++ b/client.go @@ -87,16 +87,18 @@ func DialWith(dial ios.DialFunc, op ...client.Option) (cli *Client, err error) { c.SetOption(op...) //自定义选项 c.Event.OnReadFrom = protocol.ReadFrom //分包 c.Event.OnDealMessage = cli.handlerDealMessage //解析数据并处理 - //无数据超时时间是60秒,30秒发送一个心跳包 - c.GoTimerWriter(30*time.Second, func(w ios.MoreWriter) error { - bs := protocol.MHeart.Frame().Bytes() - _, err := w.Write(bs) - return err - }) - - f := protocol.MConnect.Frame() - if _, err = c.Write(f.Bytes()); err != nil { - c.Close() + c.Event.OnConnected = func(c *client.Client) error { + //无数据超时时间是60秒,30秒发送一个心跳包 + c.GoTimerWriter(30*time.Second, func(w ios.MoreWriter) error { + bs := protocol.MHeart.Frame().Bytes() + _, err := w.Write(bs) + return err + }) + f := protocol.MConnect.Frame() + if _, err = c.Write(f.Bytes()); err != nil { + c.Close() + } + return nil } }) if err != nil { diff --git a/extend/pull-kline-mysql.go b/extend/pull-kline-mysql.go index 81a0220..e2a36c0 100644 --- a/extend/pull-kline-mysql.go +++ b/extend/pull-kline-mysql.go @@ -43,7 +43,7 @@ func (this *PullKlineMysql) Name() string { } func (this *PullKlineMysql) Run(ctx context.Context, m *tdx.Manage) error { - limit := chans.NewWaitLimit(uint(this.Config.Limit)) + limit := chans.NewWaitLimit(this.Config.Limit) //1. 获取所有股票代码 codes := this.Config.Codes diff --git a/extend/pull-kline.go b/extend/pull-kline.go index 0b721e3..067746b 100644 --- a/extend/pull-kline.go +++ b/extend/pull-kline.go @@ -105,7 +105,7 @@ func (this *PullKline) DayKlines(code string) (Klines, error) { } func (this *PullKline) Run(ctx context.Context, m *tdx.Manage) error { - limit := chans.NewWaitLimit(uint(this.Config.Limit)) + limit := chans.NewWaitLimit(this.Config.Limit) //1. 获取所有股票代码 codes := this.Config.Codes diff --git a/extend/spider-ths.go b/extend/spider-ths.go index 40537a5..1908f32 100644 --- a/extend/spider-ths.go +++ b/extend/spider-ths.go @@ -114,15 +114,11 @@ func GetTHSDayKline(code string, _type uint8) ([]*Kline, error) { } total := conv.Int(m["total"]) + sortYears := conv.Interfaces(m["sortYear"]) priceFactor := conv.Float64(m["priceFactor"]) prices := strings.Split(conv.String(m["price"]), ",") dates := strings.Split(conv.String(m["dates"]), ",") volumes := strings.Split(conv.String(m["volumn"]), ",") - start := conv.String(m["start"]) - t, err := time.Parse("20060102", start) - if err != nil { - return nil, err - } //好像到了22点,总数量会比实际多1 if total == len(dates)+1 && total == len(volumes)+1 { @@ -133,31 +129,43 @@ func GetTHSDayKline(code string, _type uint8) ([]*Kline, error) { return nil, fmt.Errorf("total=%d prices=%d dates=%d volumns=%d", total, len(prices), len(dates), len(volumes)) } - ls := []*Kline(nil) + mYear := make(map[int][]string) + index := 0 + for i, v := range sortYears { + if ls := conv.Ints(v); len(ls) == 2 { + year := conv.Int(ls[0]) + length := conv.Int(ls[1]) + if i == len(sortYears)-1 { + mYear[year] = dates[index:] + break + } + mYear[year] = dates[index : index+length] + index += length + } + } - year := t.Year() - lastDate := "" - for i := 0; i < total; i++ { - //当日前变小时(12xx变01xx),说明过了1年,除非该股票停牌了1年多则数据错误 - if dates[i] < lastDate { - year++ + ls := []*Kline(nil) + i := 0 + nowYear := time.Now().Year() + for year := 1990; year <= nowYear; year++ { + for _, d := range mYear[year] { + x, err := time.Parse("0102", d) + if err != nil { + return nil, err + } + x = time.Date(year, x.Month(), x.Day(), 15, 0, 0, 0, time.Local) + low := protocol.Price(conv.Float64(prices[i*4+0]) * 1000 / priceFactor) + ls = append(ls, &Kline{ + Code: protocol.AddPrefix(code), + Date: x.Unix(), + Open: protocol.Price(conv.Float64(prices[i*4+1])*1000/priceFactor) + low, + High: protocol.Price(conv.Float64(prices[i*4+2])*1000/priceFactor) + low, + Low: low, + Close: protocol.Price(conv.Float64(prices[i*4+3])*1000/priceFactor) + low, + Volume: (conv.Int64(volumes[i]) + 50) / 100, + }) + i++ } - lastDate = dates[i] - x, err := time.Parse("0102", dates[i]) - if err != nil { - return nil, err - } - x = time.Date(year, x.Month(), x.Day(), 15, 0, 0, 0, time.Local) - low := protocol.Price(conv.Float64(prices[i*4+0]) * 1000 / priceFactor) - ls = append(ls, &Kline{ - Code: protocol.AddPrefix(code), - Date: x.Unix(), - Open: protocol.Price(conv.Float64(prices[i*4+1])*1000/priceFactor) + low, - High: protocol.Price(conv.Float64(prices[i*4+2])*1000/priceFactor) + low, - Low: low, - Close: protocol.Price(conv.Float64(prices[i*4+3])*1000/priceFactor) + low, - Volume: (conv.Int64(volumes[i]) + 50) / 100, - }) } return ls, nil diff --git a/go.mod b/go.mod index cf322c1..af1d332 100644 --- a/go.mod +++ b/go.mod @@ -5,10 +5,10 @@ go 1.20 require ( github.com/glebarez/go-sqlite v1.22.0 github.com/go-sql-driver/mysql v1.7.0 - github.com/injoyai/base v1.2.17 + github.com/injoyai/base v1.2.15 github.com/injoyai/conv v1.2.5 - github.com/injoyai/ios v0.0.10 - github.com/injoyai/logs v1.0.9 + github.com/injoyai/ios v1.2.2 + github.com/injoyai/logs v1.0.12 github.com/robfig/cron/v3 v3.0.1 golang.org/x/text v0.16.0 xorm.io/core v0.7.3 @@ -17,7 +17,7 @@ require ( require ( github.com/dustin/go-humanize v1.0.1 // indirect - github.com/fatih/color v1.14.1 // indirect + github.com/fatih/color v1.18.0 // indirect github.com/goccy/go-json v0.8.1 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/uuid v1.5.0 // indirect @@ -31,7 +31,7 @@ require ( github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/stretchr/testify v1.9.0 // indirect github.com/syndtr/goleveldb v1.0.0 // indirect - golang.org/x/sys v0.22.0 // indirect + golang.org/x/sys v0.25.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect modernc.org/libc v1.37.6 // indirect diff --git a/go.sum b/go.sum index 2b7595e..907d985 100644 --- a/go.sum +++ b/go.sum @@ -6,9 +6,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= -github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ= github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc= @@ -27,14 +26,14 @@ github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/injoyai/base v1.2.17 h1:+qYeCSeEMWgmTla+LBC0Ozan9ysS4mV0ne5nfMt9opU= -github.com/injoyai/base v1.2.17/go.mod h1:NfCQjml3z2pCvQ3J3YcOXtecqXD0xVPKjo4YTsMLhr8= +github.com/injoyai/base v1.2.15 h1:K/ysPqZl7vgNUAz/jpG1IdDpzdSMWvUfoJL+1gPdM9g= +github.com/injoyai/base v1.2.15/go.mod h1:NfCQjml3z2pCvQ3J3YcOXtecqXD0xVPKjo4YTsMLhr8= github.com/injoyai/conv v1.2.5 h1:G4OCyF0NTZul5W1u9IgXDOhW4/zmIigdPKXFHQGmv1M= github.com/injoyai/conv v1.2.5/go.mod h1:s05l3fQJQ4mT4VX+KIdbvCWQB0YzZHprmUfUu2uxd1k= -github.com/injoyai/ios v0.0.10 h1:Zd37Rwp90PYV5eFhirR0LJ+ni/aYLSCAYgHltk/ZzJA= -github.com/injoyai/ios v0.0.10/go.mod h1:zLTmvQmIbdTf7zZxymOVxbxvvSeUMpcs4SCVPDT9BOc= -github.com/injoyai/logs v1.0.9 h1:Wq7rCVIQKcPx+z+lzKQb2qyDK4TML/cgmaSZN9tx33c= -github.com/injoyai/logs v1.0.9/go.mod h1:CLchJCGhb39Obyrci816R+KMtbxZhgPs0FuikhyixK4= +github.com/injoyai/ios v1.2.2 h1:fAPWBL6t22DiE2ZEpBgf5bzyVQTcm2ZhLMkM+JFPhZA= +github.com/injoyai/ios v1.2.2/go.mod h1:DJVJGQFQvqF80CeJVabFOm6AKilqc/m8MFvz39Uy5ow= +github.com/injoyai/logs v1.0.12 h1:f7syIGZMTg9ZzhJhdd3tzaPdxkMhdKsncGaxljqIiYE= +github.com/injoyai/logs v1.0.12/go.mod h1:+dKEL6GvaFqqVRatqUBiCicJbZnAgtj7hVs824Src4s= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= @@ -42,11 +41,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= @@ -92,13 +88,10 @@ golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= @@ -113,8 +106,8 @@ gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/protocol/frame.go b/protocol/frame.go index c2ab7c4..9a9056a 100644 --- a/protocol/frame.go +++ b/protocol/frame.go @@ -39,6 +39,19 @@ type Frame struct { Data []byte //数据 } +/* +Bytes + +0c00000000011c001c002d0500003030303030310900010000000a0000000000000000000000 + +Prefix: 0c +MsgID: 0208d301 +Control: 01 +Length: 1c00 +Length: 1c00 +Type: 2d05 +000030303030303104000100a401a40100000000000000000000 +*/ func (this *Frame) Bytes() types.Bytes { length := uint16(len(this.Data) + 2) data := make([]byte, 12+len(this.Data)) diff --git a/protocol/model_kline.go b/protocol/model_kline.go index 6d581bd..eac6554 100644 --- a/protocol/model_kline.go +++ b/protocol/model_kline.go @@ -86,6 +86,27 @@ func (this *Kline) RiseRate() float64 { type kline struct{} +/* +Frame +Prefix: 0c +MsgID: 0208d301 +Control: 01 +Length: 1c00 +Length: 1c00 +Type: 2d05 +Data: 000030303030303104000100a401a40100000000000000000000 + +Data: +Exchange: 00 +Unknown: 00 +Code: 303030303031 +Type: 04 +Unknown: 00 +Unknown: 0100 +Start: a401 +Count: a401 +Append: 00000000000000000000 +*/ func (kline) Frame(Type uint8, code string, start, count uint16) (*Frame, error) { if count > 800 { return nil, errors.New("单次数量不能超过800") @@ -116,7 +137,6 @@ func (kline) Decode(bs []byte, c KlineCache) (*KlineResp, error) { if len(bs) < 2 { return nil, errors.New("数据长度不足") } - resp := &KlineResp{ Count: Uint16(bs[:2]), }