define.go 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. package client
  2. import "tickserver/framework/event"
  3. import "sync"
  4. import "errors"
  5. import "time"
  6. import "strings"
  7. import "io"
  8. import "log"
  9. import "math"
  10. import "compress/gzip"
  11. import "encoding/binary"
  12. import "os"
  13. import "fmt"
  14. const (
  15. LmaxPrefix = "lmax_"
  16. OandaPrefix = "oanda_"
  17. EasyForexPrefix = "easyforex_"
  18. CtpPrefix = "ctp_"
  19. FixPrefix = "fix_"
  20. DzhPrefix = "dzh_"
  21. SaxoPrefix = "saxo_"
  22. )
  23. // 周期定义
  24. const (
  25. TK = 0
  26. S1 = 1
  27. S2 = 2
  28. S3 = 3
  29. S4 = 4
  30. S5 = 5
  31. S15 = 15
  32. S30 = 30
  33. M1 = 1 * 60
  34. M2 = 2 * 60
  35. M3 = 3 * 60
  36. M4 = 4 * 60
  37. M5 = 5 * 60
  38. M15 = 15 * 60
  39. M30 = 30 * 60
  40. H1 = 60 * 60
  41. H2 = 2 * 60 * 60
  42. H4 = 4 * 60 * 60
  43. D1 = 24 * 3600
  44. W1 = 7 * 24 * 3600
  45. MN1 = 30 * 24 * 3600
  46. )
  47. var PeriodNameMap = map[int]string{
  48. TK: "Tick",
  49. S1: "S1",
  50. S2: "S2",
  51. S3: "S3",
  52. S4: "S4",
  53. S5: "S5",
  54. S15: "S15",
  55. S30: "S30",
  56. M1: "M1",
  57. M2: "M2",
  58. M3: "M3",
  59. M4: "M4",
  60. M5: "M5",
  61. M15: "M15",
  62. M30: "M30",
  63. H1: "H1",
  64. H2: "H2",
  65. H4: "H4",
  66. D1: "D1",
  67. W1: "W1",
  68. MN1: "MN1",
  69. }
  70. var ErrNotEnough = errors.New("Not enough data")
  71. var TimeNow = int64(-1)
  72. type PP [2]float64 // [0]为价格, [1]为数量
  73. // 实时行情数据
  74. type Market struct {
  75. InsId string `json:"insId"` // 产品ID
  76. Timestamp int64 `json:"ts"` // 时间戳
  77. Close float64 `json:"close"` // 昨日收盘价
  78. Open float64 `json:"open"` // 今日开盘价
  79. High float64 `json:"high"` // 当日最高价
  80. Low float64 `json:"low"` // 当日最低价
  81. AllVolume float64 `json:"allVolume"` // 当日成交量
  82. AllAmount float64 `json:"allAmount"` // 成交额
  83. LastPrice float64 `json:"last"` // 最新价
  84. Volume float64 `json:"volume"` // 本次成交量(增量)
  85. Bids []PP `json:"bids"` // 申买
  86. Asks []PP `json:"asks"` // 申卖
  87. ins *Instrument
  88. }
  89. type Instrument struct {
  90. Id string `json:"insId"` // ID = 前缀+原始ID
  91. Name string `json:"name"` // 名称
  92. Typ string `json:"type"` // 用来区分种类
  93. ExId string `json:"exid"` // 交易所ID
  94. PriceInc float64 `json:"priceInc"` // 最小加价
  95. Margin float64 `json:"margin"` // 保证金
  96. StartTime int64 `json:"st"` // 上市时间
  97. EndTime int64 `json:"et"` // 下市时间
  98. mu sync.Mutex
  99. mk *Market
  100. mkPublisher event.EventPublisher // mk数据事件
  101. }
  102. func (ins *Instrument) OnMarket() *event.Event {
  103. return ins.mkPublisher.Event()
  104. }
  105. func (ins *Instrument) SetMk(mk *Market) {
  106. ins.mu.Lock()
  107. ins.mk = mk
  108. ins.mu.Unlock()
  109. mk.SetIns(ins)
  110. ins.mkPublisher.Publish(mk) //异步
  111. }
  112. func (ins *Instrument) GetMk() *Market {
  113. ins.mu.Lock()
  114. if ins.mk == nil {
  115. ins.mk = &Market{
  116. ins: ins,
  117. InsId: ins.Id,
  118. }
  119. }
  120. mk := *ins.mk
  121. ins.mu.Unlock()
  122. return &mk
  123. }
  124. func (ins *Instrument) FmtPrice(f float64) string {
  125. if f == math.MaxFloat64 || math.IsInf(f, 0) || math.IsNaN(f) {
  126. return "-"
  127. }
  128. pt := ins.PriceInc
  129. if pt < 0.0000001 {
  130. return fmt.Sprintf("%.8f", f)
  131. } else if pt < 0.000001 {
  132. return fmt.Sprintf("%.7f", f)
  133. } else if pt < 0.00001 {
  134. return fmt.Sprintf("%.6f", f)
  135. } else if pt < 0.0001 {
  136. return fmt.Sprintf("%.5f", f)
  137. } else if pt < 0.001 {
  138. return fmt.Sprintf("%.4f", f)
  139. } else if pt < 0.01 {
  140. return fmt.Sprintf("%.3f", f)
  141. } else if pt < 0.1 {
  142. return fmt.Sprintf("%.2f", f)
  143. } else if pt < 1. {
  144. return fmt.Sprintf("%.1f", f)
  145. } else {
  146. return fmt.Sprintf("%d", int(f))
  147. }
  148. }
  149. type DBConf struct {
  150. DBDriver string // mysql, sqlite
  151. DSN string // dsn = fmt.Sprintf("root:fzm@1001@/%s?charset=%s", dbName, "utf8")
  152. DBName string // fzmdb
  153. }
  154. // 历史数据应答参数
  155. type HistoryReply struct {
  156. Url string `json:"url"`
  157. St int64 `json:"st"`
  158. Et int64 `json:"et"`
  159. N int `json:"n"`
  160. }
  161. type Tick struct {
  162. // InsId string `json:"insId"` // 产品ID
  163. Timestamp int64 `json:"ts"` // 时间戳
  164. Price float64 `json:"last"` // 最新价
  165. Volume float64 `json:"volume"` // 本次成交量(增量)
  166. Bid PP `json:"bids"` // 申买
  167. Ask PP `json:"asks"` // 申卖
  168. }
  169. type Candle struct {
  170. Timestamp int64 `json:"ts"`
  171. Open float64 `json:"open"`
  172. High float64 `json:"high"`
  173. Low float64 `json:"low"`
  174. Close float64 `json:"close"`
  175. RealVolums float64 `json:"realVol"`
  176. TickVolums float64 `json:"tickVol"`
  177. }
  178. // 实时数据订阅参数
  179. type SubArgs struct {
  180. InsId string `json:"insId"` // 产品Id
  181. Code int64 `json:"code"` // 客户端代码
  182. IsCancel bool `json:"cancel"` // 是否取消订阅
  183. }
  184. func InsIdPrefix(insId string) string {
  185. return strings.Split(insId, "_")[0]
  186. }
  187. func getTime(ts int64) time.Time {
  188. if ts < 0 {
  189. return time.Now()
  190. }
  191. return time.Unix(ts/1000, (ts%1000)*1e6)
  192. }
  193. func GetTime(ts int64) time.Time {
  194. return getTime(ts)
  195. }
  196. func DebugDelay(prefix, insId string, ts int64) {
  197. // for debug delay
  198. now := time.Now()
  199. d := int64(float64(now.UnixNano())*1e-6) - ts
  200. if d > 1000 {
  201. log.Println(prefix, "delay > 1000ms", insId, d, getTime(ts))
  202. }
  203. }
  204. func (m *Market) SetIns(ins *Instrument) {
  205. m.ins = ins
  206. }
  207. func UnzipC(r io.Reader) ([]Candle, error) {
  208. return unzipC(r)
  209. }
  210. func unzipC(r io.Reader) ([]Candle, error) {
  211. gr, err := gzip.NewReader(r)
  212. if err != nil {
  213. return nil, err
  214. }
  215. defer gr.Close()
  216. candles := []Candle{}
  217. for {
  218. c, err := ReadCandleBinary(gr)
  219. if err != nil {
  220. if err != io.EOF {
  221. return candles, err
  222. }
  223. break
  224. }
  225. if math.IsNaN(c.Open*2) || math.IsInf(c.Open*2, 0) {
  226. continue
  227. }
  228. if math.IsNaN(c.High*2) || math.IsInf(c.High*2, 0) {
  229. continue
  230. }
  231. if math.IsNaN(c.Low*2) || math.IsInf(c.Low*2, 0) {
  232. continue
  233. }
  234. if math.IsNaN(c.Close*2) || math.IsInf(c.Close*2, 0) {
  235. continue
  236. }
  237. candles = append(candles, *c)
  238. }
  239. return candles, nil
  240. }
  241. func UnzipT(r io.Reader) ([]Tick, error) {
  242. return unzipT(r)
  243. }
  244. func unzipT(r io.Reader) ([]Tick, error) {
  245. gr, err := gzip.NewReader(r)
  246. if err != nil {
  247. return nil, err
  248. }
  249. defer gr.Close()
  250. ticks := []Tick{}
  251. for {
  252. t, err := ReadTickBinary(gr)
  253. if err != nil {
  254. if err != io.EOF {
  255. return nil, err
  256. }
  257. break
  258. }
  259. if math.IsNaN(t.Price) || math.IsInf(t.Price*2, 0) {
  260. continue
  261. }
  262. ticks = append(ticks, *t)
  263. }
  264. return ticks, nil
  265. }
  266. func readTickFile(fname string) ([]Tick, error) {
  267. f, err := os.Open(fname)
  268. if err != nil {
  269. // log.Fatal(err.Error() + fname)
  270. return nil, err
  271. }
  272. defer f.Close()
  273. return unzipT(f)
  274. }
  275. func readCandleFile(fname string) ([]Candle, error) {
  276. f, err := os.Open(fname)
  277. if err != nil {
  278. return nil, err
  279. }
  280. defer f.Close()
  281. return unzipC(f)
  282. }
  283. func ReadCandleFile(fname string) ([]Candle, error) {
  284. return readCandleFile(fname)
  285. }
  286. func ReadTickFile(fname string) ([]Tick, error) {
  287. return readTickFile(fname)
  288. }
  289. func ReadTickBinary(r io.Reader) (*Tick, error) {
  290. t := &Tick{}
  291. err := binary.Read(r, binary.LittleEndian, t)
  292. if err != nil {
  293. return nil, err
  294. }
  295. return t, nil
  296. }
  297. func ReadCandleBinary(r io.Reader) (*Candle, error) {
  298. c := &Candle{}
  299. err := binary.Read(r, binary.LittleEndian, c)
  300. if err != nil {
  301. return nil, err
  302. }
  303. return c, nil
  304. }