gitee.com/quant1x/engine@v1.8.4/factors/kline.go (about) 1 package factors 2 3 import ( 4 "gitee.com/quant1x/engine/cache" 5 "gitee.com/quant1x/engine/datasource/base" 6 "gitee.com/quant1x/exchange" 7 "gitee.com/quant1x/gox/api" 8 "gitee.com/quant1x/num" 9 "gitee.com/quant1x/pandas" 10 ) 11 12 // BasicKLine 基础日K线 13 func BasicKLine(securityCode string) pandas.DataFrame { 14 securityCode = exchange.CorrectSecurityCode(securityCode) 15 filename := cache.KLineFilename(securityCode) 16 df := pandas.ReadCSV(filename) 17 return df 18 } 19 20 // KLine 加载日K线宽表 21 func KLine(securityCode string) pandas.DataFrame { 22 securityCode = exchange.CorrectSecurityCode(securityCode) 23 filename := cache.WideFilename(securityCode) 24 df := pandas.ReadCSV(filename) 25 return df 26 } 27 28 // KLineToWeekly 日线转周线 29 // 30 // deprecated: 不推荐使用 31 func KLineToWeekly(kline pandas.DataFrame) pandas.DataFrame { 32 // 周线 33 var df pandas.DataFrame 34 //date,open,close,high,low,volume,amount,up,down 35 var wdate string 36 var o, c, h, l, v, a num.DType 37 var bv, sv, ba, sa num.DType 38 var prevClose num.DType 39 for i := 0; i < kline.Nrow(); i++ { 40 m := kline.IndexOf(i) 41 //date,open,close,high,low,volume,amount,up,down 42 // 周线日期以最后一天的日期为准 43 _date, ok := m["date"].(string) 44 if ok { 45 wdate = _date 46 } 47 // 周线开盘价以第一天OPEN为准 48 _open, ok := m["open"].(num.DType) 49 if ok && o == num.DType(0) { 50 o = _open 51 } 52 // 周线的收盘价以本周最后一个交易日的CLOSE为准 53 _close, ok := m["close"].(num.DType) 54 if ok { 55 c = _close 56 } 57 // 涨幅 58 zf := (c/prevClose - 1.00) * 100.00 59 _high, ok := m["high"].(num.DType) 60 if ok && h == num.DType(0) { 61 h = _high 62 } 63 if h < _high { 64 h = _high 65 } 66 _low, ok := m["low"].(num.DType) 67 if ok && l == num.DType(0) { 68 l = _low 69 } 70 if l > _low { 71 l = _low 72 } 73 _vol, ok := m["volume"] 74 if ok { 75 v += num.Any2DType(_vol) 76 } 77 _amount, ok := m["amount"].(num.DType) 78 if ok { 79 a += _amount 80 } 81 _bv, ok := m["bv"] 82 if ok { 83 bv += num.Any2DType(_bv) 84 } 85 _sv, ok := m["sv"] 86 if ok { 87 sv += num.Any2DType(_sv) 88 } 89 _ba, ok := m["ba"] 90 if ok { 91 ba += num.Any2DType(_ba) 92 } 93 _sa, ok := m["sa"] 94 if ok { 95 sa += num.Any2DType(_sa) 96 } 97 dt, _ := api.ParseTime(wdate) 98 w := int(dt.Weekday()) 99 last := false 100 today := exchange.IndexToday() 101 if wdate == today { 102 last = true 103 } 104 // 如果是周五 105 if !last && w == 5 { 106 last = true 107 } 108 if !last { 109 nextDate := exchange.NextTradeDate(wdate) 110 ndt, _ := api.ParseTime(nextDate) 111 nw := int(ndt.Weekday()) 112 if nw < w || api.DifferDays(ndt, dt) >= 7 { 113 last = true 114 } 115 } 116 if last { 117 df0 := pandas.NewDataFrame( 118 pandas.NewSeriesWithType(pandas.SERIES_TYPE_STRING, "date", wdate), 119 pandas.NewSeriesWithType(pandas.SERIES_TYPE_DTYPE, "open", o), 120 pandas.NewSeriesWithType(pandas.SERIES_TYPE_DTYPE, "close", c), 121 pandas.NewSeriesWithType(pandas.SERIES_TYPE_DTYPE, "high", h), 122 pandas.NewSeriesWithType(pandas.SERIES_TYPE_DTYPE, "low", l), 123 pandas.NewSeriesWithType(pandas.SERIES_TYPE_DTYPE, "volume", v), 124 pandas.NewSeriesWithType(pandas.SERIES_TYPE_DTYPE, "amount", a), 125 pandas.NewSeriesWithType(pandas.SERIES_TYPE_DTYPE, "bv", bv), 126 pandas.NewSeriesWithType(pandas.SERIES_TYPE_DTYPE, "sv", sv), 127 pandas.NewSeriesWithType(pandas.SERIES_TYPE_DTYPE, "ba", ba), 128 pandas.NewSeriesWithType(pandas.SERIES_TYPE_DTYPE, "sa", sa), 129 pandas.NewSeriesWithType(pandas.SERIES_TYPE_DTYPE, "zf", zf), 130 ) 131 df = df.Concat(df0) 132 wdate = "" 133 prevClose = c 134 o = num.DType(0) 135 c = num.DType(0) 136 h = num.DType(0) 137 l = num.DType(0) 138 v = num.DType(0) 139 a = num.DType(0) 140 } 141 } 142 return df 143 } 144 145 // MovingAverage 移动平均线(MA) 146 type MovingAverage struct { 147 MA5 float64 // 5日均线 148 MA10 float64 // 10日均线 149 MA20 float64 // 20日均线 150 } 151 152 // 由日线计算日线以上级别的K线 153 func periodKLine(checkPeriod func(date ...string) (s, e string), securityCode string, cacheKLine ...[]base.KLine) (df pandas.DataFrame) { 154 baseKLines := []base.KLine{} 155 if len(cacheKLine) > 0 { 156 baseKLines = cacheKLine[0] 157 } else { 158 baseKLines = base.LoadBasicKline(securityCode) 159 } 160 if len(baseKLines) == 0 { 161 return 162 } 163 164 var klines []base.KLine 165 var kline base.KLine 166 length := len(baseKLines) 167 for i, v := range baseKLines { 168 // 确定时间, 周线的日期是本周内最后一个交易日 169 if len(kline.Date) == 0 { 170 // 重新计算周线, 先确认周线范围 171 ws, we := checkPeriod(v.Date) 172 _ = ws 173 //dates := trading.TradeRange(ws, we) 174 //days := len(dates) 175 //days = 7 176 //if days > 0 { 177 periodLastDate := exchange.FixTradeDate(we) 178 //if periodLastDate == "2023-07-30" { 179 // fmt.Println(1) 180 //} 181 offset := i 182 for { 183 destDate := baseKLines[offset].Date 184 if destDate < periodLastDate { 185 offset++ 186 } 187 if offset >= length { 188 periodLastDate = destDate 189 break 190 } else if baseKLines[offset].Date == periodLastDate { 191 periodLastDate = baseKLines[offset].Date 192 break 193 } else if baseKLines[offset].Date > periodLastDate { 194 periodLastDate = destDate 195 break 196 } 197 } 198 kline.Date = periodLastDate 199 //} else { 200 // return 201 //} 202 } 203 // 周线开盘价以第一天OPEN为准 204 if kline.Open == num.DType(0) { 205 kline.Open = v.Open 206 } 207 // 周线的收盘价以本周最后一个交易日的CLOSE为准 208 kline.Close = v.Close 209 if kline.High == num.DType(0) { 210 kline.High = v.High 211 } else if kline.High < v.High { 212 kline.High = v.High 213 } 214 if kline.Low == num.DType(0) { 215 kline.Low = v.Low 216 } else if kline.Low > v.Low { 217 kline.Low = v.Low 218 } 219 kline.Volume += v.Volume 220 kline.Amount += v.Amount 221 222 // 切换下一周 223 if kline.Date == v.Date || i+1 >= len(baseKLines) { 224 kline.Date = v.Date 225 klines = append(klines, kline) 226 kline = base.KLine{} 227 } 228 } 229 df = pandas.LoadStructs(klines) 230 //fmt.Println(df) 231 return 232 } 233 234 // WeeklyKLine 周线 235 func WeeklyKLine(securityCode string, cacheKLine ...[]base.KLine) (df pandas.DataFrame) { 236 return periodKLine(api.GetWeekDay, securityCode, cacheKLine...) 237 } 238 239 // MonthlyKLine 月K线 240 func MonthlyKLine(securityCode string, cacheKLine ...[]base.KLine) (df pandas.DataFrame) { 241 return periodKLine(api.GetMonthDay, securityCode, cacheKLine...) 242 }