From 04378dadf0331bfe5b7ae29b76a26cfdf319aa14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=92=B1=E7=BA=AF=E5=87=80?= <1113655791@qq.com> Date: Mon, 9 Jun 2025 00:18:51 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0HistoryMinuteTrades=E5=92=8CK?= =?UTF-8?q?lines?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- protocol/model_history_minute_trade.go | 50 +++++++++++++++++++- protocol/model_kline.go | 64 ++++++++++++++++++++++++++ protocol/unit.go | 11 ++++- 3 files changed, 123 insertions(+), 2 deletions(-) diff --git a/protocol/model_history_minute_trade.go b/protocol/model_history_minute_trade.go index 5c9d6e9..e05e647 100644 --- a/protocol/model_history_minute_trade.go +++ b/protocol/model_history_minute_trade.go @@ -4,12 +4,14 @@ import ( "errors" "fmt" "github.com/injoyai/conv" + "time" ) // HistoryMinuteTradeResp 历史分时交易比实时少了单量 type HistoryMinuteTradeResp struct { Count uint16 - List []*HistoryMinuteTrade + List HistoryMinuteTrades + //List []*HistoryMinuteTrade } type HistoryMinuteTrade struct { @@ -92,3 +94,49 @@ func (historyMinuteTrade) Decode(bs []byte, code string) (*HistoryMinuteTradeRes return resp, nil } + +type HistoryMinuteTrades []*HistoryMinuteTrade + +func (this HistoryMinuteTrades) Kline(date string) (k *Kline, err error) { + k = &Kline{} + for i, v := range this { + switch i { + case 0: + k.Time, err = time.Parse("2006010215:04", date+v.Time) + if err != nil { + return + } + k.Open = v.Price + k.High = v.Price + k.Low = v.Price + k.Close = v.Price + case len(this) - 1: + k.Close = v.Price + } + k.High = conv.Select(v.Price > k.High, v.Price, k.High) + k.Low = conv.Select(v.Price < k.Low, v.Price, k.Low) + k.Volume += int64(v.Volume) + k.Amount += v.Amount() + } + return +} + +// MinuteKline 分时K线 +func (this HistoryMinuteTrades) MinuteKline(date string) (Klines, error) { + m := make(map[string]HistoryMinuteTrades) + for _, v := range this { + v.Time = conv.Select(v.Time > "09:00", v.Time, "09:00") + m[v.Time] = append(m[v.Time], v) + } + + ls := Klines(nil) + for _, v := range m { + k, err := v.Kline(date) + if err != nil { + return nil, err + } + ls = append(ls, k) + } + ls.Sort() + return ls, nil +} diff --git a/protocol/model_kline.go b/protocol/model_kline.go index 7df5c1f..b95dacd 100644 --- a/protocol/model_kline.go +++ b/protocol/model_kline.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/injoyai/base/types" "github.com/injoyai/conv" + "sort" "time" ) @@ -209,3 +210,66 @@ func FixKlineTime(ks []*Kline) []*Kline { } return ks } + +type Klines []*Kline + +func (this Klines) Len() int { + return len(this) +} + +func (this Klines) Swap(i, j int) { + this[i], this[j] = this[j], this[i] +} + +func (this Klines) Less(i, j int) bool { + return this[i].Time.Before(this[j].Time) +} + +func (this Klines) Sort() { + sort.Sort(this) +} + +// Kline 计算多个K线,成一个K线 +func (this Klines) Kline() *Kline { + if this == nil { + return new(Kline) + } + k := new(Kline) + for i, v := range this { + switch i { + case 0: + k.Open = v.Open + k.High = v.High + k.Low = v.Low + k.Close = v.Close + case len(this) - 1: + k.Close = v.Close + k.Time = v.Time + } + if v.High > k.High { + k.High = v.High + } + if v.Low < k.Low { + k.Low = v.Low + } + k.Volume += v.Volume + k.Amount += v.Amount + } + return k +} + +// Merge 合并K线,1分钟转成5,15,30分钟等 +func (this Klines) Merge(n int) Klines { + if this == nil { + return nil + } + ks := []*Kline(nil) + for i := 0; i < len(this); i += n { + if i+n > len(this) { + ks = append(ks, this[i:].Kline()) + } else { + ks = append(ks, this[i:i+n].Kline()) + } + } + return ks +} diff --git a/protocol/unit.go b/protocol/unit.go index 9ed9a5b..284fd3c 100644 --- a/protocol/unit.go +++ b/protocol/unit.go @@ -271,15 +271,24 @@ func IsETF(code string) bool { return false } -// AddPrefix 添加股票代码前缀,针对股票生效,例如000001,会增加前缀sz000001(平安银行),而不是sh000001(上证指数) +// AddPrefix 添加股票/基金代码前缀,针对股票/基金生效,例如000001,会增加前缀sz000001(平安银行),而不是sh000001(上证指数) func AddPrefix(code string) string { if len(code) == 6 { switch { case code[:1] == "6": + //上海股票 code = ExchangeSH.String() + code case code[:1] == "0": + //深圳股票 code = ExchangeSZ.String() + code case code[:2] == "30": + //深圳股票 + code = ExchangeSZ.String() + code + case code[:3] == "510" || code[:3] == "511" || code[:3] == "512" || code[:3] == "513" || code[:3] == "515": + //上海基金 + code = ExchangeSH.String() + code + case code[:3] == "159": + //深圳基金 code = ExchangeSZ.String() + code } }