gitee.com/quant1x/engine@v1.8.4/factors/dataset_wide.go (about) 1 package factors 2 3 import ( 4 "context" 5 "gitee.com/quant1x/engine/cache" 6 "gitee.com/quant1x/engine/datasource/base" 7 "gitee.com/quant1x/exchange" 8 "gitee.com/quant1x/gotdx/quotes" 9 "gitee.com/quant1x/gox/api" 10 "gitee.com/quant1x/num" 11 "slices" 12 ) 13 14 // DataWideKLine 宽表 15 type DataWideKLine struct { 16 Manifest 17 } 18 19 func init() { 20 summary := __mapDataSets[BaseWideKLine] 21 _ = cache.Register(&DataWideKLine{Manifest: Manifest{DataSummary: summary}}) 22 } 23 24 func (this *DataWideKLine) Clone(date string, code string) DataSet { 25 summary := __mapDataSets[BaseWideKLine] 26 var dest = DataWideKLine{ 27 Manifest: Manifest{ 28 DataSummary: summary, 29 Date: date, 30 Code: code, 31 }, 32 } 33 return &dest 34 } 35 36 func (this *DataWideKLine) Init(ctx context.Context, date string) error { 37 // 恢复交易数据的最早日期默认值 38 base.RestoreBeginDateOfHistoricalTradingData() 39 _ = ctx 40 _ = date 41 return nil 42 } 43 44 func (this *DataWideKLine) Update(date string) { 45 pullWideByDate(this.GetSecurityCode(), date) 46 } 47 48 func (this *DataWideKLine) Repair(date string) { 49 this.Update(date) 50 } 51 52 func (this *DataWideKLine) Increase(snapshot quotes.Snapshot) { 53 _ = snapshot 54 } 55 56 func (this *DataWideKLine) Print(code string, date ...string) { 57 _ = code 58 _ = date 59 } 60 61 // 通过日期拉取宽表数据 62 func pullWideByDate(securityCode, date string) []SecurityFeature { 63 securityCode = exchange.CorrectSecurityCode(securityCode) 64 // 1. 加载缓存 65 filename := cache.WideFilename(securityCode) 66 var list []SecurityFeature 67 var beginDate string // 补数据的开始日期 68 var endDate string // 补数据的结束日期 69 var cacheBeginDate, cacheEndDate string 70 err := api.CsvToSlices(filename, &list) 71 if err != nil || len(list) == 0 { 72 // 如果文件为空, 暂定从1990-12-19 73 cacheBeginDate = exchange.MARKET_CH_FIRST_LISTTIME 74 cacheEndDate = cacheBeginDate 75 beginDate = cacheBeginDate 76 } else { 77 //list = list[:len(list)-1] 78 cacheBeginDate = list[0].Date 79 last := list[len(list)-1] 80 cacheEndDate = last.Date 81 // 以缓存文件最后一条记录的日期 82 beginDate = cacheEndDate 83 } 84 // 2. 确定补齐数据的日期 85 endDate = exchange.FixTradeDate(date) 86 // 2.1 结束日期经过交易日历的校对处理一次 87 //logger.Warnf("[%s]: begin=%s, end= %s", securityCode, beginDate, endDate) 88 if len(beginDate) == 0 { 89 beginDate = exchange.MARKET_CH_FIRST_LISTTIME 90 } 91 dates := exchange.TradingDateRange(beginDate, endDate) 92 n := len(dates) 93 if n == 0 { 94 // 这种情况的原因是传入的date小于缓存的最后一条记录的日期 95 beginDate = endDate 96 } else if n == 1 { 97 // 传入日期和缓存最后一条记录的日期相同 98 beginDate = dates[0] 99 endDate = dates[0] 100 } else { 101 beginDate = dates[0] 102 endDate = dates[n-1] 103 } 104 // 3. 补齐日线, 日线是必须要有的, 也肯定会有 105 // 数据为空, 从基础K线获取K线部分 106 klines := base.CheckoutKLines(securityCode, endDate) 107 kline_length := len(klines) 108 if kline_length == 0 { 109 // K线为空, 返回空 110 return nil 111 } else { 112 // 校验wide缓存和k线缓存的开始日期是否对齐 113 klsBeginDate := klines[0].Date 114 klsEndDate := klines[kline_length-1].Date 115 if cacheBeginDate == klsBeginDate { 116 // 如果缓存的开始日期和k线的开始日期相同, 没有问题 117 } else { 118 // 如果缓存的开始日期和k线的开始日期不同, 则认为数据错乱, 清空 119 clear(list) 120 // 设置缓存开始日期为k线的开始日期 121 cacheBeginDate = klsBeginDate 122 // 设置缓存结束日期为k线的开始日期 123 cacheEndDate = klsBeginDate 124 beginDate = cacheBeginDate 125 } 126 _ = klsEndDate 127 } 128 // 4. 确定缓存记录数 129 list_length := len(list) 130 // 5. 如果kline比wide数据多 131 if kline_length > list_length { 132 list = slices.Grow(list, kline_length) 133 } 134 transBeginDate := base.GetBeginDateOfHistoricalTradingData() 135 transBeginDate = exchange.FixTradeDate(transBeginDate) 136 for i, v := range klines { 137 featureDate := v.Date 138 cacheDate := v.Date 139 // 强制更新标志 140 forceUpdate := false 141 if i < list_length && featureDate >= transBeginDate { 142 checksum := list[i].CheckSum() 143 forceUpdate = checksum == 0 144 } 145 if !forceUpdate && v.Date < beginDate { 146 continue 147 } 148 if v.Date > endDate { 149 break 150 } 151 var info SecurityFeature 152 // 复制k线 153 info.Date = v.Date 154 info.Open = v.Open 155 info.Close = v.Close 156 info.High = v.High 157 info.Low = v.Low 158 info.Volume = int64(v.Volume) 159 info.Amount = v.Amount 160 info.Up = v.Up 161 info.Down = v.Down 162 // 附加成交数据 163 if featureDate >= transBeginDate { 164 // 成交数据 165 trans := base.CheckoutTransactionData(securityCode, featureDate, true) 166 if len(trans) > 0 { 167 cover := CountInflow(trans, securityCode, featureDate) 168 // 修正f10的缓存, 应该是缓存日期为准 169 f10 := GetL5F10(securityCode, cacheDate) 170 if f10 != nil { 171 cover.OpenTurnZ = f10.TurnZ(cover.OpenVolume) 172 cover.CloseTurnZ = f10.TurnZ(cover.CloseVolume) 173 } 174 info.OpenVolume = cover.OpenVolume 175 info.OpenTurnZ = cover.OpenTurnZ 176 info.CloseVolume = cover.CloseVolume 177 info.CloseTurnZ = cover.CloseTurnZ 178 info.Volume = cover.InnerVolume + cover.OuterVolume 179 info.InnerVolume = cover.InnerVolume 180 info.OuterVolume = cover.OuterVolume 181 info.InnerAmount = cover.InnerAmount 182 info.OuterAmount = cover.OuterAmount 183 } 184 } 185 if i < list_length { 186 list[i] = info 187 } else { 188 list = append(list, info) 189 } 190 } 191 // 6. 最后再修订数据 192 lastClose := 0.000 193 for i := 0; i < len(list); i++ { 194 v := &list[i] 195 // 6.1 修正last_close和change_rate 196 if i == 0 { 197 v.LastClose = v.Open 198 } else { 199 v.LastClose = lastClose 200 } 201 v.ChangeRate = num.NetChangeRate(v.LastClose, v.Close) 202 lastClose = v.Close 203 // 6.2 修正up和down 204 //// 指数类, up和down对应涨跌家数 205 //// 股票类, 对应内外盘 206 //if v.Up == 0 { 207 // v.Up = int(v.OuterVolume) 208 //} 209 //if v.Down == 0 { 210 // v.Down = int(v.InnerVolume) 211 //} 212 } 213 214 // 7. 保存文件 215 _ = api.SlicesToCsv(filename, list) 216 return list 217 }