quote.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. package models
  2. import (
  3. "context"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "mtp2_if/config"
  8. "mtp2_if/db"
  9. "mtp2_if/logger"
  10. "mtp2_if/rediscli"
  11. "mtp2_if/utils"
  12. "strings"
  13. "time"
  14. "github.com/go-viper/mapstructure/v2"
  15. "go.mongodb.org/mongo-driver/bson"
  16. "go.mongodb.org/mongo-driver/bson/primitive"
  17. )
  18. // CycleType 周期类型
  19. type CycleType int
  20. const (
  21. // CycleTypeSecond 周期类型 - 秒
  22. CycleTypeSecond CycleType = 0
  23. // CycleTypeMinutes1 周期类型 - 1分钟
  24. CycleTypeMinutes1 CycleType = 1
  25. // CycleTypeMinutes5 周期类型 - 5分钟
  26. CycleTypeMinutes5 CycleType = 2
  27. // CycleTypeMinutes30 周期类型 - 30分钟
  28. CycleTypeMinutes30 CycleType = 3
  29. // CycleTypeMinutes60 周期类型 - 60分钟
  30. CycleTypeMinutes60 CycleType = 4
  31. // CycleTypeMinutes120 周期类型 - 2小时
  32. CycleTypeMinutes120 CycleType = 120
  33. // CycleTypeMinutes240 周期类型 - 4小时
  34. CycleTypeMinutes240 CycleType = 240
  35. // CycleTypeMinutesDay 周期类型 - 日线
  36. CycleTypeMinutesDay CycleType = 11
  37. // CycleTypeWeek 周期类型 - 周线
  38. CycleTypeWeek CycleType = 12
  39. // CycleTypeMonth 周期类型 - 月线
  40. CycleTypeMonth CycleType = 13
  41. // CycleTypeYear 周期类型 - 年线
  42. CycleTypeYear CycleType = 14
  43. // CycleTypeTik 周期类型 - Tik
  44. CycleTypeTik CycleType = 10
  45. )
  46. // CycleData MongoDB中历史数据模型
  47. type CycleData struct {
  48. ID primitive.ObjectID `json:"-" bson:"_id"` // id
  49. GC string `bson:"GC"` // 商品代码
  50. ST int `json:"-" bson:"ST"` // 时间戳
  51. SST string `bson:"SST"` // 时间文本
  52. Open int `bson:"Open"` // 开盘价
  53. High int `bson:"High"` // 最高价
  54. Low int `bson:"Low"` // 最低价
  55. Close int `bson:"Close"` // 收盘价
  56. TV int `bson:"TV"` // 总量
  57. TT int `bson:"TT"` // 总金额
  58. HV int `bson:"HV"` // 持仓量
  59. SP int `bson:"SP"` // 结算价,日线周期(包括)以上才有
  60. FI bool `json:"FI"` // 是否补充数据
  61. }
  62. // TikData MongoDB中Tik数据模型
  63. type TikData struct {
  64. ID primitive.ObjectID `json:"-" bson:"_id"` // id
  65. GC string `bson:"GC"` // 商品代码
  66. TD int `bson:"TD"` // 交易日时间戳
  67. AT int `bson:"AT"` // 行情时间戳
  68. SAT string `bson:"SAT"` // 行情时间文本
  69. PE int `bson:"PE"` // 现价
  70. Vol int `bson:"Vol"` // 现量
  71. TT int `bson:"TT"` // 现金额
  72. Bid int `bson:"Bid"` // 买价
  73. BV int `bson:"BV"` // 买量
  74. Ask int `bson:"Ask"` // 卖价
  75. AV int `bson:"AV"` // 卖量
  76. HV int `bson:"HV"` // 持仓量
  77. HI int `bson:"HI"` // 单笔持仓
  78. TDR int `bson:"TDR"` // 交易方向
  79. TK int `bson:"TK"` // 交易类型
  80. OId int `bson:"OId"` // 行情序号
  81. }
  82. // Quoteday 行情盘面
  83. type Quoteday struct {
  84. Id int64 `mapstructure:"" xorm:"pk autoincr BIGINT(20)"`
  85. Exchangedate int64 `mapstructure:"ExchangeDate" xorm:"not null BIGINT(20)"` // 交易日
  86. Goodscode string `mapstructure:"GoodsCode" xorm:"not null unique CHAR(10)"` // 商品代码
  87. Exchangecode int `mapstructure:"ExchangeCode" xorm:"INT(11)"` // 交易所代码
  88. Preclose int64 `mapstructure:"Preclose" xorm:"default 0 BIGINT(20)"` // 昨收
  89. Opentime int64 `mapstructure:"Opentime" xorm:"BIGINT(20)"` // 开盘时间
  90. Opened int64 `mapstructure:"Opened" xorm:"not null default 0 BIGINT(20)"` // 开盘价
  91. Highest int64 `mapstructure:"Highest" xorm:"not null default 0 BIGINT(20)"` // 最高价
  92. Lowest int64 `mapstructure:"Lowest" xorm:"not null default 0 BIGINT(20)"` // 最低价
  93. Lasttime string `mapstructure:"Lasttime" xorm:"VARCHAR(20)"` // 行情时间(只有现价变化行情时间才变化)
  94. Utclasttime int64 `mapstructure:"Utclasttime" xorm:"not null BIGINT(20)"` // utc的行情时间
  95. Last int64 `mapstructure:"Last" xorm:"not null BIGINT(20)"` // 最新价
  96. Lastvolume int64 `mapstructure:"Lastvolume" xorm:"default 0 BIGINT(20)"` // 最新成交量
  97. Lastturnover int64 `mapstructure:"Lastturnover" xorm:"default 0 BIGINT(20)"` // 最新成交金额
  98. Totalbidvolume int64 `mapstructure:"Totalbidvolume" xorm:"default 0 BIGINT(20)"` // 外盘
  99. Totalaskvolume int64 `mapstructure:"Totalaskvolume" xorm:"default 0 BIGINT(20)"` // 内盘
  100. Totalvolume int64 `mapstructure:"Totalvolume" xorm:"default 0 BIGINT(20)"` // 总量
  101. Totalturnover int64 `mapstructure:"Totalturnover" xorm:"default 0 BIGINT(20)"` // 总金额
  102. Bid int64 `mapstructure:"Bid" xorm:"default 0 BIGINT(20)"` // 买1
  103. Bid2 int64 `mapstructure:"Bid2" xorm:"default 0 BIGINT(20)"` // 买2
  104. Bid3 int64 `mapstructure:"Bid3" xorm:"default 0 BIGINT(20)"` // 买3
  105. Bid4 int64 `mapstructure:"Bid4" xorm:"default 0 BIGINT(20)"` // 买4
  106. Bid5 int64 `mapstructure:"Bid5" xorm:"default 0 BIGINT(20)"` // 买5
  107. Bidvolume int64 `mapstructure:"Bidvolume" xorm:"default 0 BIGINT(20)"` // 买量1
  108. Bidvolume2 int64 `mapstructure:"Bidvolume2" xorm:"default 0 BIGINT(20)"` // 买量2
  109. Bidvolume3 int64 `mapstructure:"Bidvolume3" xorm:"default 0 BIGINT(20)"` // 买量3
  110. Bidvolume4 int64 `mapstructure:"Bidvolume4" xorm:"default 0 BIGINT(20)"` // 买量4
  111. Bidvolume5 int64 `mapstructure:"Bidvolume5" xorm:"default 0 BIGINT(20)"` // 买量5
  112. Ask int64 `mapstructure:"Ask" xorm:"default 0 BIGINT(20)"` // 卖1
  113. Ask2 int64 `mapstructure:"Ask2" xorm:"default 0 BIGINT(20)"` // 卖2
  114. Ask3 int64 `mapstructure:"Ask3" xorm:"default 0 BIGINT(20)"` // 卖3
  115. Ask4 int64 `mapstructure:"Ask4" xorm:"default 0 BIGINT(20)"` // 卖4
  116. Ask5 int64 `mapstructure:"Ask5" xorm:"default 0 BIGINT(20)"` // 卖5
  117. Askvolume int64 `mapstructure:"Askvolume" xorm:"default 0 BIGINT(20)"` // 卖量1
  118. Askvolume2 int64 `mapstructure:"Askvolume2" xorm:"default 0 BIGINT(20)"` // 卖量2
  119. Askvolume3 int64 `mapstructure:"Askvolume3" xorm:"default 0 BIGINT(20)"` // 卖量3
  120. Askvolume4 int64 `mapstructure:"Askvolume4" xorm:"default 0 BIGINT(20)"` // 卖量4
  121. Askvolume5 int64 `mapstructure:"Askvolume5" xorm:"default 0 BIGINT(20)"` // 卖量5
  122. Presettle int64 `mapstructure:"Presettle" xorm:"default 0 BIGINT(20)"` // 昨结价
  123. Settle int64 `mapstructure:"Settle" xorm:"default 0 BIGINT(20)"` // 结算价
  124. Preholdvolume int64 `mapstructure:"Preholdvolume" xorm:"default 0 BIGINT(20)"` // 昨持仓
  125. Holdvolume int64 `mapstructure:"Holdvolume" xorm:"default 0 BIGINT(20)"` // 持仓
  126. Averageprice int64 `mapstructure:"Averageprice" xorm:"default 0 BIGINT(20)"` // 均价
  127. Orderid int64 `mapstructure:"Orderid" xorm:"default 0 BIGINT(20)"` // 序号
  128. Limitup int64 `mapstructure:"Limitup" xorm:"default 0 BIGINT(20)"` // 涨停价
  129. Limitdown int64 `mapstructure:"Limitdown" xorm:"default 0 BIGINT(20)"` // 跌停价
  130. Inventory int64 `mapstructure:"Inventory" xorm:"default 0 BIGINT(20)"` // 库存
  131. Holdincrement int64 `mapstructure:"Holdincrement" xorm:"default 0 BIGINT(20)"` // 单笔持仓
  132. Iscleared int `mapstructure:"Iscleared" xorm:"INT(11)"` // 是否清盘标志
  133. Issettled int `mapstructure:"Issettled" xorm:"INT(11)"` // 是否结算标志
  134. Bidqueueinfo string `mapstructure:"Bidqueueinfo" xorm:"VARCHAR(2000)"` // 大利市买港股用
  135. Askqueueinfo string `mapstructure:"Askqueueinfo" xorm:"VARCHAR(2000)"` // 大利市卖港股用
  136. Bidorderid int64 `mapstructure:"Bidorderid" xorm:"BIGINT(20)"` // 买单号1
  137. Bidorderid2 int64 `mapstructure:"Bidorderid2" xorm:"BIGINT(20)"` // 买单号2
  138. Bidorderid3 int64 `mapstructure:"Bidorderid3" xorm:"BIGINT(20)"` // 买单号3
  139. Bidorderid4 int64 `mapstructure:"Bidorderid4" xorm:"BIGINT(20)"` // 买单号4
  140. Bidorderid5 int64 `mapstructure:"Bidorderid5" xorm:"BIGINT(20)"` // 买单号5
  141. Askorderid int64 `mapstructure:"Askorderid" xorm:"BIGINT(20)"` // 卖单号1
  142. Askorderid2 int64 `mapstructure:"Askorderid2" xorm:"BIGINT(20)"` // 卖单号2
  143. Askorderid3 int64 `mapstructure:"Askorderid3" xorm:"BIGINT(20)"` // 卖单号3
  144. Askorderid4 int64 `mapstructure:"Askorderid4" xorm:"BIGINT(20)"` // 卖单号4
  145. Askorderid5 int64 `mapstructure:"Askorderid5" xorm:"BIGINT(20)"` // 卖单号5
  146. Lastlot int64 `mapstructure:"Lastlot" xorm:"BIGINT(20)"` // 最新成交手数
  147. Totallot int64 `mapstructure:"Totallot" xorm:"BIGINT(20)"` // 总手数
  148. Strikeprice int64 `mapstructure:"Strikeprice" xorm:"BIGINT(20)"` // 发行价
  149. Cleartime int64 `mapstructure:"Cleartime" xorm:"BIGINT(20)"` // 清盘时间
  150. Calloptionpremiums int64 `mapstructure:"Calloptionpremiums" xorm:"default 0 BIGINT(20)"` // 认购期权1
  151. Calloptionpremiums2 int64 `mapstructure:"Calloptionpremiums2" xorm:"default 0 BIGINT(20)"` // 认购期权2
  152. Calloptionpremiums3 int64 `mapstructure:"Calloptionpremiums3" xorm:"default 0 BIGINT(20)"` // 认购期权3
  153. Calloptionpremiums4 int64 `mapstructure:"Calloptionpremiums4" xorm:"default 0 BIGINT(20)"` // 认购期权4
  154. Calloptionpremiums5 int64 `mapstructure:"Calloptionpremiums5" xorm:"default 0 BIGINT(20)"` // 认购期权5
  155. Putoptionpremiums int64 `mapstructure:"Putoptionpremiums" xorm:"default 0 BIGINT(20)"` // 认沽期权1
  156. Putoptionpremiums2 int64 `mapstructure:"Putoptionpremiums2" xorm:"default 0 BIGINT(20)"` // 认沽期权2
  157. Putoptionpremiums3 int64 `mapstructure:"Putoptionpremiums3" xorm:"default 0 BIGINT(20)"` // 认沽期权3
  158. Putoptionpremiums4 int64 `mapstructure:"Putoptionpremiums4" xorm:"default 0 BIGINT(20)"` // 认沽期权4
  159. Putoptionpremiums5 int64 `mapstructure:"Putoptionpremiums5" xorm:"default 0 BIGINT(20)"` // 认沽期权5
  160. Nontotalvolume int64 `mapstructure:"Nontotalvolume" xorm:"default 0 BIGINT(20)"` // 非交易总量
  161. Nontotalholdervolume int64 `mapstructure:"Nontotalholdervolume" xorm:"default 0 BIGINT(20)"` // 非交易持仓量
  162. Nontotalturnover int64 `mapstructure:"Nontotalturnover" xorm:"default 0 BIGINT(20)"` // 非交易总金额
  163. Nontotallot int64 `mapstructure:"Nontotallot" xorm:"default 0 BIGINT(20)"` // 非交易总手数
  164. Publictradetype string `mapstructure:"Publictradetype" xorm:"VARCHAR(2)"` // 公共交易标志类型 港股专用
  165. Iep int64 `mapstructure:"Iep" xorm:"default 0 BIGINT(20)"` // 平衡价 港股专用
  166. Iev int64 `mapstructure:"Iev" xorm:"default 0 BIGINT(20)"` // 平衡量 港股专用
  167. Grepmarketprice int64 `mapstructure:"Grepmarketprice" xorm:"default 0 BIGINT(20)"` // 暗盘价 港股专用
  168. Bid6 int64 `mapstructure:"Bid6" xorm:"default 0 BIGINT(20)"` // 买6
  169. Bid7 int64 `mapstructure:"Bid7" xorm:"default 0 BIGINT(20)"` // 买7
  170. Bid8 int64 `mapstructure:"Bid8" xorm:"default 0 BIGINT(20)"` // 买8
  171. Bid9 int64 `mapstructure:"Bid9" xorm:"default 0 BIGINT(20)"` // 买9
  172. Bid10 int64 `mapstructure:"Bid10" xorm:"default 0 BIGINT(20)"` // 买10
  173. Bidvolume6 int64 `mapstructure:"Bidvolume6" xorm:"default 0 BIGINT(20)"` // 买量6
  174. Bidvolume7 int64 `mapstructure:"Bidvolume7" xorm:"default 0 BIGINT(20)"` // 买量7
  175. Bidvolume8 int64 `mapstructure:"Bidvolume8" xorm:"default 0 BIGINT(20)"` // 买量8
  176. Bidvolume9 int64 `mapstructure:"Bidvolume9" xorm:"default 0 BIGINT(20)"` // 买量9
  177. Bidvolume10 int64 `mapstructure:"Bidvolume10" xorm:"default 0 BIGINT(20)"` // 买量10
  178. Ask6 int64 `mapstructure:"Ask6" xorm:"default 0 BIGINT(20)"` // 卖6
  179. Ask7 int64 `mapstructure:"Ask7" xorm:"default 0 BIGINT(20)"` // 卖7
  180. Ask8 int64 `mapstructure:"Ask8" xorm:"default 0 BIGINT(20)"` // 卖8
  181. Ask9 int64 `mapstructure:"Ask9" xorm:"default 0 BIGINT(20)"` // 卖9
  182. Ask10 int64 `mapstructure:"Ask10" xorm:"default 0 BIGINT(20)"` // 卖10
  183. Askvolume6 int64 `mapstructure:"Askvolume6" xorm:"default 0 BIGINT(20)"` // 卖量6
  184. Askvolume7 int64 `mapstructure:"Askvolume7" xorm:"default 0 BIGINT(20)"` // 卖量7
  185. Askvolume8 int64 `mapstructure:"Askvolume8" xorm:"default 0 BIGINT(20)"` // 卖量8
  186. Askvolume9 int64 `mapstructure:"Askvolume9" xorm:"default 0 BIGINT(20)"` // 卖量9
  187. Askvolume10 int64 `mapstructure:"Askvolume10" xorm:"default 0 BIGINT(20)"` // 卖量10
  188. Bidordervolume int64 `mapstructure:"Bidordervolume" xorm:"default 0 BIGINT(20)"` // 买单量1
  189. Bidordervolume2 int64 `mapstructure:"Bidordervolume2" xorm:"default 0 BIGINT(20)"` // 买单量2
  190. Bidordervolume3 int64 `mapstructure:"Bidordervolume3" xorm:"default 0 BIGINT(20)"` // 买单量3
  191. Bidordervolume4 int64 `mapstructure:"Bidordervolume4" xorm:"default 0 BIGINT(20)"` // 买单量4
  192. Bidordervolume5 int64 `mapstructure:"Bidordervolume5" xorm:"default 0 BIGINT(20)"` // 买单量5
  193. Bidordervolume6 int64 `mapstructure:"Bidordervolume6" xorm:"default 0 BIGINT(20)"` // 买单量6
  194. Bidordervolume7 int64 `mapstructure:"Bidordervolume7" xorm:"default 0 BIGINT(20)"` // 买单量7
  195. Bidordervolume8 int64 `mapstructure:"Bidordervolume8" xorm:"default 0 BIGINT(20)"` // 买单量8
  196. Bidordervolume9 int64 `mapstructure:"Bidordervolume9" xorm:"default 0 BIGINT(20)"` // 买单量9
  197. Bidordervolume10 int64 `mapstructure:"Bidordervolume10" xorm:"default 0 BIGINT(20)"` // 买单量10
  198. Askordervolume int64 `mapstructure:"Askordervolume" xorm:"default 0 BIGINT(20)"` // 卖单量1
  199. Askordervolume2 int64 `mapstructure:"Askordervolume2" xorm:"default 0 BIGINT(20)"` // 卖单量2
  200. Askordervolume3 int64 `mapstructure:"Askordervolume3" xorm:"default 0 BIGINT(20)"` // 卖单量3
  201. Askordervolume4 int64 `mapstructure:"Askordervolume4" xorm:"default 0 BIGINT(20)"` // 卖单量4
  202. Askordervolume5 int64 `mapstructure:"Askordervolume5" xorm:"default 0 BIGINT(20)"` // 卖单量5
  203. Askordervolume6 int64 `mapstructure:"Askordervolume6" xorm:"default 0 BIGINT(20)"` // 卖单量6
  204. Askordervolume7 int64 `mapstructure:"Askordervolume7" xorm:"default 0 BIGINT(20)"` // 卖单量7
  205. Askordervolume8 int64 `mapstructure:"Askordervolume8" xorm:"default 0 BIGINT(20)"` // 卖单量8
  206. Askordervolume9 int64 `mapstructure:"Askordervolume9" xorm:"default 0 BIGINT(20)"` // 卖单量9
  207. Askordervolume10 int64 `mapstructure:"Askordervolume10" xorm:"default 0 BIGINT(20)"` // 卖单量10
  208. }
  209. // TableName is Quoteday
  210. func (*Quoteday) TableName() string {
  211. return "quoteday"
  212. }
  213. // GetHistoryCycleDatas 获取历史数据
  214. // 参数 cycleType CycleType 周期类型
  215. // 参数 goodsCode string 商品代码
  216. // 参数 startTime time.Time 开始时间(闭区间)
  217. // 参数 endTime time.Time 结束时间(闭区间)
  218. // 参数 count int 条数
  219. // 参数 isAscForST bool 是否按时间顺序排序,默认为时间倒序排序
  220. // 返回值 []CycleData 历史数据
  221. // 返回值 error 错误
  222. func GetHistoryCycleDatas(cycleType CycleType, goodsCode string, startTime, endTime *time.Time, count int, isAscForST bool) ([]CycleData, error) {
  223. db := db.GetMongoDB()
  224. // 获取目标Collection
  225. collection := "mincycle"
  226. switch cycleType {
  227. case CycleTypeTik:
  228. collection = "quotetik"
  229. case CycleTypeMinutes1:
  230. collection = "mincycle"
  231. case CycleTypeMinutes5:
  232. collection = "min5cycle"
  233. case CycleTypeMinutes30:
  234. collection = "min30cycle"
  235. case CycleTypeMinutes60:
  236. collection = "min60cycle"
  237. case CycleTypeMinutes240:
  238. collection = "min240cycle"
  239. case CycleTypeMinutesDay:
  240. collection = "daycycle"
  241. case CycleTypeWeek:
  242. collection = "weekcycle"
  243. case CycleTypeMonth:
  244. collection = "monthcycle"
  245. case CycleTypeYear:
  246. collection = "yearcycle"
  247. default:
  248. return nil, errors.New("不支持的周期类型")
  249. }
  250. c := db.Collection(collection)
  251. // 按时间排序
  252. sort := "-ST"
  253. if isAscForST {
  254. sort = "ST"
  255. }
  256. // 查询数据
  257. var cycleDatas []CycleData
  258. m := bson.M{"GC": goodsCode}
  259. if startTime != nil && endTime == nil {
  260. m["ST"] = bson.M{"$gte": startTime.Unix()}
  261. } else if startTime == nil && endTime != nil {
  262. m["ST"] = bson.M{"$lte": endTime.Unix()}
  263. } else if startTime != nil && endTime != nil {
  264. m["ST"] = bson.M{"$gte": startTime.Unix(), "$lte": endTime.Unix()}
  265. }
  266. query := c.Find(context.Background(), m)
  267. if count > 0 {
  268. query = query.Limit(int64(count))
  269. }
  270. if err := query.Sort(sort).All(&cycleDatas); err != nil {
  271. return nil, err
  272. }
  273. return cycleDatas, nil
  274. }
  275. // GetHistoryTikDatas 获取历史数据
  276. // 参数 goodsCode string 商品代码
  277. // 参数 startTime time.Time 开始时间(闭区间)
  278. // 参数 endTime time.Time 结束时间(闭区间)
  279. // 参数 count int 条数
  280. // 参数 isAscForST bool 是否按时间顺序排序,默认为时间倒序排序
  281. // 返回值 []TikData Tik数据
  282. // 返回值 error 错误
  283. func GetHistoryTikDatas(goodsCode string, startTime, endTime *time.Time, count int, isAscForST bool) ([]TikData, error) {
  284. db := db.GetMongoDB()
  285. // 获取目标Collection
  286. collection := "quotetik"
  287. c := db.Collection(collection)
  288. // 按时间排序
  289. sort := "-_id"
  290. if isAscForST {
  291. sort = "id"
  292. }
  293. // 查询数据
  294. var tikDatas []TikData
  295. m := bson.M{"GC": goodsCode}
  296. if startTime != nil && endTime == nil {
  297. m["AT"] = bson.M{"$gte": startTime.Unix()}
  298. } else if startTime == nil && endTime != nil {
  299. m["AT"] = bson.M{"$lte": endTime.Unix()}
  300. } else if startTime != nil && endTime != nil {
  301. m["AT"] = bson.M{"$gte": startTime.Unix(), "$lte": endTime.Unix()}
  302. }
  303. query := c.Find(context.Background(), m)
  304. if count > 0 {
  305. query = query.Limit(int64(count))
  306. }
  307. if err := query.Sort(sort).All(&tikDatas); err != nil {
  308. return nil, err
  309. }
  310. return tikDatas, nil
  311. }
  312. // GetQuoteDays 获取目标商品的盘面数据
  313. // 参数 goodsCodes string 商品代码字串,以“,”分隔
  314. // 返回 []Quoteday 盘面数据
  315. // 返回 error error
  316. func GetQuoteDays(goodsCodes string) ([]Quoteday, error) {
  317. if config.SerCfg.MySQLCfg.Enabled == 0 {
  318. // 使用 Redis 盘面
  319. return QueryRedisQuoteDays(goodsCodes)
  320. }
  321. engine := db.GetMySQLEngine()
  322. datas := make([]Quoteday, 0)
  323. if len(goodsCodes) > 0 {
  324. // 指定商品代码查询
  325. // 处理商品代码, 让其可作为sql的in条件内容。 例如, 原字符串 ru2201,CU2406, => 处理成 'ru2201','CU2406'
  326. goodsCodes = strings.Trim(goodsCodes, ",")
  327. sCode := strings.Split(goodsCodes, ",")
  328. for i := range sCode {
  329. // 如果没有单引号, 则加上单引号
  330. if !strings.Contains(sCode[i], "'") {
  331. sCode[i] = "'" + sCode[i] + "'"
  332. }
  333. }
  334. Instr := strings.Join(sCode, ",")
  335. if err := engine.Where(fmt.Sprintf("goodscode in (%s)", Instr)).Find(&datas); err != nil {
  336. return nil, err
  337. }
  338. } else {
  339. // 不指定则查所有
  340. if err := engine.Find(&datas); err != nil {
  341. return nil, err
  342. }
  343. }
  344. return datas, nil
  345. }
  346. // SetRedisQuoteDays 将盘面数据同步到Redis
  347. func SetRedisQuoteDays() (err error) {
  348. engine := db.GetMySQLEngine()
  349. datas := make([]Quoteday, 0)
  350. if err = engine.Find(&datas); err != nil {
  351. return
  352. }
  353. b, err := json.Marshal(datas)
  354. if err != nil {
  355. return
  356. }
  357. redisCli := rediscli.GetRedisClient()
  358. err = redisCli.Set("Tourist:QuoteDay", b, 0).Err()
  359. return
  360. }
  361. // QueryRedisQuoteDays 从Redis读取盘面数据
  362. func QueryRedisQuoteDays(goodsCodes string) (quoteDays []Quoteday, err error) {
  363. exchangeCode := "250"
  364. quoteDays = make([]Quoteday, 0)
  365. redisCli := rediscli.GetRedisClient()
  366. for _, goodsCode := range strings.Split(goodsCodes, ",") {
  367. var m map[string]string
  368. m, err = redisCli.HGetAll(fmt.Sprintf("QuoteDay:%s_%s", exchangeCode, goodsCode)).Result()
  369. if err != nil {
  370. return
  371. }
  372. if len(m) == 0 {
  373. return
  374. }
  375. var quoteDay Quoteday
  376. config := &mapstructure.DecoderConfig{
  377. WeaklyTypedInput: true, // 启用弱类型转换,允许字符串自动转换为数字
  378. Result: &quoteDay,
  379. }
  380. decoder, err := mapstructure.NewDecoder(config)
  381. if err != nil {
  382. return quoteDays, err
  383. }
  384. err = decoder.Decode(m)
  385. if err != nil {
  386. return quoteDays, err
  387. }
  388. quoteDays = append(quoteDays, quoteDay)
  389. }
  390. return
  391. }
  392. // GetRedisQuoteDays 从Redis读取盘面数据(游客)
  393. func GetRedisQuoteDays(goodsCodes []string) (quoteDays []Quoteday, err error) {
  394. redisCli := rediscli.GetRedisClient()
  395. b, err := redisCli.Get("Tourist:QuoteDay").Bytes()
  396. if err != nil {
  397. return
  398. }
  399. var datas []Quoteday
  400. if err = json.Unmarshal(b, &datas); err != nil {
  401. return
  402. }
  403. quoteDays = make([]Quoteday, 0)
  404. for _, item := range datas {
  405. if utils.InArray(len(goodsCodes), func(i int) bool { return goodsCodes[i] == item.Goodscode }) {
  406. quoteDays = append(quoteDays, item)
  407. }
  408. }
  409. return
  410. }
  411. var Done chan bool
  412. func StartSyncRedisQuoteDay() {
  413. ticker := time.NewTicker(2 * time.Second)
  414. Done = make(chan bool)
  415. go func() {
  416. for {
  417. select {
  418. case <-Done:
  419. ticker.Stop()
  420. return
  421. case <-ticker.C:
  422. // 在这里执行定时任务的代码
  423. if err := SetRedisQuoteDays(); err != nil {
  424. logger.GetLogger().Errorf("Sync Redis failed: %s", err.Error())
  425. }
  426. }
  427. }
  428. }()
  429. }