gitee.com/quant1x/engine@v1.8.4/services/task_update_misc.go (about) 1 package services 2 3 import ( 4 "gitee.com/quant1x/engine/cache" 5 "gitee.com/quant1x/engine/factors" 6 "gitee.com/quant1x/engine/market" 7 "gitee.com/quant1x/engine/models" 8 "gitee.com/quant1x/exchange" 9 "gitee.com/quant1x/gotdx/quotes" 10 "gitee.com/quant1x/gox/api" 11 "gitee.com/quant1x/gox/coroutine" 12 "gitee.com/quant1x/gox/logger" 13 "gitee.com/quant1x/gox/progressbar" 14 "gitee.com/quant1x/gox/runtime" 15 "time" 16 ) 17 18 // 更新快照 19 func jobUpdateMiscAndSnapshot() { 20 now := time.Now() 21 updateInRealTime, _ := exchange.CanUpdateInRealtime() 22 // 集合竞价时段更新数据 23 if updateInRealTime && exchange.CheckCallAuctionTime(now) { 24 realtimeUpdateMiscAndSnapshot() 25 } else { 26 if runtime.Debug() { 27 realtimeUpdateMiscAndSnapshot() 28 } 29 } 30 } 31 32 var ( 33 snapshotDate = cache.DefaultCanReadDate() 34 mapSnapshot = map[string][]quotes.Snapshot{} 35 onceSnapshot coroutine.RollingOnce 36 ) 37 38 func resetSnapshotCache() { 39 date := cache.DefaultCanReadDate() 40 if date > snapshotDate { 41 clear(mapSnapshot) 42 snapshotDate = date 43 factors.SwitchDate(snapshotDate) 44 } 45 } 46 47 // realtimeUpdateMiscAndSnapshot 更新快照缓存 48 func realtimeUpdateMiscAndSnapshot() { 49 onceSnapshot.Do(resetSnapshotCache) 50 moduleName := "执行[misc]" 51 logger.Infof("%s: begin", moduleName) 52 allCodes := market.GetCodeList() 53 count := len(allCodes) 54 currentDate := cache.DefaultCanReadDate() 55 bar := progressbar.NewBar(barIndexUpdateExchangeAndSnapshot, moduleName, count) 56 for _, securityCode := range allCodes { 57 bar.Add(1) 58 if api.StartsWith(securityCode, []string{"88"}) { 59 securityCode = "sh" + securityCode 60 } 61 v := models.GetTickFromMemory(securityCode) 62 if v == nil || v.Date != currentDate { 63 // 如果snapshot缓存无效, 或者日期不是当前日期, 跳过 64 continue 65 } 66 //kind := exchange.AssertCode(securityCode) 67 timestamp := time.Now() 68 // 1. 修订日期 69 v.Date = currentDate 70 securityCode := v.SecurityCode 71 misc := factors.GetL5Misc(securityCode) 72 if misc == nil { 73 logger.Errorf("加载misc[%s-%s]失败", currentDate, securityCode) 74 misc = &factors.Misc{ 75 Date: currentDate, 76 Code: securityCode, 77 } 78 } else { 79 misc.Date = currentDate 80 } 81 // 2. 计算开盘和收盘的成交量 82 misc.OpenVolume = int64(v.OpenVolume) 83 misc.CloseVolume = int64(v.CloseVolume) 84 // 计算开盘换手z和收盘换手z 85 f10 := factors.GetL5F10(securityCode) 86 if f10 != nil { 87 misc.OpenTurnZ = f10.TurnZ(misc.OpenVolume) 88 misc.CloseTurnZ = f10.TurnZ(misc.CloseVolume) 89 } 90 // 3. 计算快照扩展数据 91 if exchange.CheckCallAuctionOpen(timestamp) { 92 // 3.1 早盘情绪有时效性 93 // 计算早盘竞价方向 94 misc.OpenBiddingDirection, misc.OpenVolumeDirection = v.CheckDirection() 95 // 3.2 计算早盘情绪 96 misc.OpenSentiment, misc.OpenConsistent = market.SnapshotSentiment(*v) 97 } else { 98 // 3.3 盘中及盘后的数据的计算都没有问题 99 // 计算收盘竞价方向 100 misc.CloseBiddingDirection, misc.CloseVolumeDirection = v.CheckDirection() 101 // 3.4 计算收盘情绪 102 misc.CloseSentiment, misc.CloseConsistent = market.SnapshotSentiment(*v) 103 } 104 // 4. 竞价上午竞价观察 105 if exchange.CheckCallAuctionOpen(timestamp) { 106 // 4.1 竞价开盘 107 if misc.BidOpen == 0 { 108 misc.BidOpen = v.Ask1 109 } 110 // 4.2 竞价结束 111 misc.BidClose = v.Price 112 // 4.3 竞价最高 113 if misc.BidHigh == 0 || misc.BidHigh < v.Ask1 { 114 misc.BidHigh = v.Ask1 115 } 116 // 4.4 竞价最低 117 if misc.BidLow == 0 || misc.BidLow > v.Ask1 { 118 misc.BidLow = v.Ask1 119 } 120 // 4.4 竞价匹配量, 竞价结束前更新 121 if v.Active == 0 { 122 misc.BidMatched = float64(v.BidVol1) 123 // 4.5 竞价未匹配量 124 if v.BidVol2 == 0 { 125 misc.BidUnmatched = float64(v.AskVol2) 126 misc.BidDirection = -1 127 } 128 if v.AskVol2 == 0 { 129 misc.BidUnmatched = float64(v.BidVol2) 130 misc.BidDirection = 1 131 } 132 } 133 } 134 // 5. 缓存数据 135 //cacheSnapshots = append(cacheSnapshots, *exchange) 136 137 // 6. 更新内存中的数据 138 factors.UpdateL5Misc(misc) 139 // 7. 刷新缓存 140 cacheList, ok := mapSnapshot[securityCode] 141 if !ok { 142 cacheList = []quotes.Snapshot{} 143 } 144 if len(cacheList) > 0 { 145 lastDay := cacheList[len(cacheList)-1].Date 146 lastServerTime := cacheList[len(cacheList)-1].ServerTime 147 if currentDate == lastDay && v.ServerTime <= lastServerTime { 148 // 时间戳在缓存之前, 忽略 149 continue 150 } 151 } 152 cacheList = append(cacheList, *v) 153 if len(cacheList) > 0 { 154 mapSnapshot[securityCode] = cacheList 155 } 156 } 157 bar.Wait() 158 // 刷新Misc快照本地cache 159 factors.RefreshL5Misc() 160 timestamp := time.Now() 161 if exchange.CheckCallAuctionOpenFinished(timestamp) || exchange.CheckCallAuctionCloseFinished(timestamp) { 162 // 早盘和尾盘集合竞价结束后刷新缓存文件 163 for _, listSnapshot := range mapSnapshot { 164 if len(listSnapshot) == 0 { 165 continue 166 } 167 // 获取第一条记录 168 first := listSnapshot[0] 169 securityCode := first.SecurityCode 170 filename := cache.SnapshotFilename(securityCode) 171 cacheList := []quotes.Snapshot{} 172 err := api.CsvToSlices(filename, &cacheList) 173 if err == nil && len(cacheList) > 0 { 174 // 缓存中最后一条记录 175 rows := len(cacheList) 176 last := cacheList[rows-1] 177 // 日期 178 lastDay := last.Date 179 // 时间戳 180 lastServerTime := last.ServerTime 181 for _, v := range listSnapshot { 182 if currentDate == lastDay && v.ServerTime <= lastServerTime { 183 // 时间戳在缓存之前, 忽略 184 continue 185 } 186 cacheList = append(cacheList, v) 187 } 188 } else { 189 // 如果缓存文件不存在, 用缓存数据 190 cacheList = listSnapshot 191 } 192 if len(cacheList) > 0 { 193 _ = api.SlicesToCsv(filename, cacheList) 194 } 195 } 196 } 197 logger.Infof("%s: end", moduleName) 198 }