增加PullTrade,用于拉取分时成交,然后计算成K线

This commit is contained in:
钱纯净
2025-06-09 00:19:30 +08:00
parent 04378dadf0
commit 78843ed6b7
5 changed files with 231 additions and 0 deletions

19
example/PullTrade/main.go Normal file
View File

@@ -0,0 +1,19 @@
package main
import (
"github.com/injoyai/logs"
"github.com/injoyai/tdx"
"github.com/injoyai/tdx/extend"
)
func main() {
pt := extend.NewPullTrade("./data/trade")
m, err := tdx.NewManage(nil)
logs.PanicErr(err)
err = pt.Pull(m, 2024, "sz000001")
logs.Err(err)
}

154
extend/pull-trade.go Normal file
View File

@@ -0,0 +1,154 @@
package extend
import (
"github.com/injoyai/conv"
"github.com/injoyai/logs"
"github.com/injoyai/tdx"
"github.com/injoyai/tdx/protocol"
"path/filepath"
"time"
)
func NewPullTrade(dir string) *PullTrade {
return &PullTrade{
Dir: dir,
}
}
type PullTrade struct {
Dir string
}
func (this *PullTrade) Pull(m *tdx.Manage, year int, code string) (err error) {
tss := protocol.HistoryMinuteTrades{}
kss1 := protocol.Klines(nil)
kss5 := protocol.Klines(nil)
kss15 := protocol.Klines(nil)
kss30 := protocol.Klines(nil)
kss60 := protocol.Klines(nil)
m.Workday.RangeYear(year, func(t time.Time) bool {
date := t.Format("20060102")
var resp *protocol.HistoryMinuteTradeResp
err = m.Do(func(c *tdx.Client) error {
resp, err = c.GetHistoryMinuteTradeAll(date, code)
return err
})
if err != nil {
logs.Err(err)
return false
}
tss = append(tss, resp.List...)
//转成分时K线
ks, err := resp.List.MinuteKline(date)
if err != nil {
logs.Err(err)
return false
}
kss1 = append(kss1, ks...)
kss5 = append(kss5, ks.Merge(5)...)
kss15 = append(kss5, ks.Merge(15)...)
kss30 = append(kss5, ks.Merge(30)...)
kss60 = append(kss5, ks.Merge(60)...)
return true
})
_ = kss5
_ = kss15
_ = kss30
_ = kss60
filename := filepath.Join(this.Dir, conv.String(year), "分时成交", code+".csv")
filename1 := filepath.Join(this.Dir, conv.String(year), "1分钟", code+".csv")
filename5 := filepath.Join(this.Dir, conv.String(year), "5分钟", code+".csv")
filename15 := filepath.Join(this.Dir, conv.String(year), "15分钟", code+".csv")
filename30 := filepath.Join(this.Dir, conv.String(year), "30分钟", code+".csv")
filename60 := filepath.Join(this.Dir, conv.String(year), "60分钟", code+".csv")
name := m.Codes.GetName(code)
err = TradeToCsv(filename, tss)
if err != nil {
return err
}
err = KlinesToCsv(filename1, code, name, kss1)
if err != nil {
return err
}
err = KlinesToCsv(filename5, code, name, kss5)
if err != nil {
return err
}
err = KlinesToCsv(filename15, code, name, kss15)
if err != nil {
return err
}
err = KlinesToCsv(filename30, code, name, kss30)
if err != nil {
return err
}
err = KlinesToCsv(filename60, code, name, kss60)
if err != nil {
return err
}
return nil
}
var (
TableTitles = []any{"日期", "时间", "代码", "名称", "开盘", "最高", "最低", "收盘", "总手", "金额", "涨幅", "涨幅比"}
)
func KlinesToCsv(filename string, code, name string, ks protocol.Klines) error {
data := [][]any{TableTitles}
for _, v := range ks {
data = append(data, []any{
v.Time.Format("20060102"),
v.Time.Format("15:04"),
code,
name,
v.Open.Float64(),
v.High.Float64(),
v.Low.Float64(),
v.Close.Float64(),
v.Volume,
v.Amount.Float64(),
v.RisePrice(),
v.RiseRate(),
})
}
buf, err := toCsv(data)
if err != nil {
return err
}
return newFile(filename, buf)
}
func TradeToCsv(filename string, ts protocol.HistoryMinuteTrades) error {
data := [][]any{TableTitles}
for _, v := range ts {
data = append(data, []any{
v.Time,
v.Price.Float64(),
v.Amount(),
v.Status,
})
}
buf, err := toCsv(data)
if err != nil {
return err
}
return newFile(filename, buf)
}

58
extend/util.go Normal file
View File

@@ -0,0 +1,58 @@
package extend
import (
"bytes"
"encoding/csv"
"github.com/injoyai/conv"
"io"
"os"
"path/filepath"
)
func toCsv(data [][]interface{}) (*bytes.Buffer, error) {
buf := bytes.NewBuffer(nil)
buf.WriteString("\xEF\xBB\xBF")
w := csv.NewWriter(buf)
for _, rows := range data {
if err := w.Write(conv.Strings(rows)); err != nil {
return nil, err
}
}
w.Flush()
return buf, nil
}
// newFile 新建文件,会覆盖
func newFile(filename string, v ...interface{}) error {
if len(v) == 0 {
return os.MkdirAll(filename, 0777)
}
dir, name := filepath.Split(filename)
if len(dir) > 0 {
if err := os.MkdirAll(dir, 0777); err != nil {
return err
}
}
if len(name) == 0 {
return nil
}
f, err := os.Create(filename)
if err != nil {
return err
}
defer f.Close()
for _, k := range v {
switch r := k.(type) {
case nil:
case io.Reader:
if _, err = io.Copy(f, r); err != nil {
return err
}
default:
if _, err = f.Write(conv.Bytes(r)); err != nil {
return err
}
}
}
return nil
}