main.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  1. // main.go
  2. package main
  3. import (
  4. "compress/gzip"
  5. "encoding/json"
  6. "errors"
  7. "flag"
  8. "fmt"
  9. "io"
  10. "log"
  11. "net/http"
  12. _ "net/http/pprof"
  13. "os"
  14. "runtime"
  15. "strconv"
  16. "strings"
  17. "time"
  18. "tickserver/client"
  19. "tickserver/markinfo"
  20. "tickserver/server/market"
  21. )
  22. const (
  23. K_STYLE = iota
  24. T_STYLE
  25. )
  26. type Options struct {
  27. Start int `json:"start"`
  28. End int `json:"end"`
  29. Total int `json:"total_size"`
  30. }
  31. type KCandle struct {
  32. X []int `json:"x"`
  33. Y [][5]float32 `json:"y"`
  34. }
  35. type KVolume struct {
  36. X []int `json:"x"`
  37. Y []float32 `json:"y"`
  38. }
  39. type KData struct {
  40. C string `json:"c"`
  41. P string `json:"p"`
  42. Action string `json:"action"`
  43. End int `json:"end"`
  44. //KOptions Options `json:"options"`
  45. Candles KCandle `json:"main"`
  46. Volumes KVolume `json:"volumes|||__ignore__"`
  47. }
  48. type TData struct {
  49. End int `json:"end"`
  50. Candles []client.Candle `json:"data"`
  51. }
  52. var saddr1 = flag.String("s1", "127.0.0.1:19528", "tick server address 1") //115.231.103.7
  53. var saddr2 = flag.String("s2", "127.0.0.1:19528", "tick server address 2") //127.0.0.1
  54. var saddr3 = flag.String("s3", "127.0.0.1:19529", "tick server address 3") //115.236.75.194
  55. var saddr4 = flag.String("s4", "127.0.0.1:9090", "tick server address 4") //19528 9090
  56. var clientDown *client.ClientSimple
  57. //var clientDownTmp *client.ClientSimple
  58. type Conf struct {
  59. Saddr1 string //
  60. Saddr2 string //
  61. Saddr3 string //
  62. Saddr4 string
  63. }
  64. func readConf() (*Conf, error) {
  65. f, err := os.Open("webproxys.json")
  66. if err != nil {
  67. return nil, err
  68. }
  69. defer f.Close()
  70. dec := json.NewDecoder(f)
  71. conf := &Conf{}
  72. err = dec.Decode(conf)
  73. if err != nil {
  74. return nil, err
  75. }
  76. return conf, nil
  77. }
  78. func connectServer() (err error) {
  79. clientDown, err = client.NewClientSimple(*saddr1, *saddr2, *saddr3, *saddr4, "./tmp")
  80. if err != nil {
  81. //log.Println("new client", err)
  82. return err
  83. }
  84. //clientDownTmp, err = client.NewClientSimple("114.215.207.24:19528", "114.215.207.24:19528", "114.215.207.24:19529", "114.215.207.24:9090", "./tmp")
  85. //if err != nil {
  86. //log.Println("new client", err)
  87. //return err
  88. //}
  89. return nil
  90. }
  91. func changeCandle(candle, candle2, candle3 client.Candle) client.Candle {
  92. newCandle := candle
  93. if newCandle.High >= newCandle.Low*1.05 || newCandle.High >= candle2.Low*1.05 || newCandle.High >= candle3.Low*1.05 {
  94. //log.Println(newCandle)
  95. var low float64
  96. if newCandle.High >= newCandle.Low*1.05 {
  97. low = newCandle.Low
  98. }
  99. if newCandle.High >= candle2.Low*1.05 {
  100. low = candle2.Low
  101. }
  102. if newCandle.High >= candle3.Low*1.05 {
  103. low = candle3.Low
  104. }
  105. if newCandle.Open > newCandle.Close {
  106. newCandle.Open = low * 1.003
  107. newCandle.Close = low * 1.002
  108. } else {
  109. newCandle.Open = low * 1.002
  110. newCandle.Close = low * 1.003
  111. }
  112. newCandle.High = low * 1.005
  113. if newCandle.Low != low {
  114. newCandle.Low = low * 1.001
  115. }
  116. }
  117. return newCandle
  118. }
  119. func getData(symbol, period, action, count, out, cb, te, ts string, style int) (string, error) {
  120. iCount, err := strconv.Atoi(count)
  121. if action != "new" && err != nil {
  122. return "", errors.New("webserver doesn't support count")
  123. }
  124. if action == "new" {
  125. iCount = 1000
  126. }
  127. periodId, ok := market.PeriodIdMap[period]
  128. if !ok {
  129. return "", errors.New("webserver doesn't support period")
  130. }
  131. periodIdOld := periodId
  132. if periodId == market.M15 || periodId == market.M30 {
  133. periodId = market.M5
  134. if periodIdOld == market.M15 {
  135. iCount *= 3
  136. }
  137. if periodIdOld == market.M30 {
  138. iCount *= 6
  139. }
  140. }
  141. if periodId == market.H2 || periodId == market.H4 {
  142. periodId = market.H1
  143. if periodIdOld == market.H2 {
  144. iCount *= 2
  145. }
  146. if periodIdOld == market.H4 {
  147. iCount *= 4
  148. }
  149. }
  150. if periodId == market.W1 || periodId == market.MN1 {
  151. periodId = market.D1
  152. if periodIdOld == market.W1 {
  153. iCount *= 7
  154. }
  155. if periodIdOld == market.MN1 {
  156. iCount *= 31
  157. }
  158. }
  159. iCount++
  160. //startTime := time.Now().UnixNano()
  161. //log.Println("step1", symbol, period, action, count, out, cb, te, ts)
  162. symbolU := strings.ToUpper(symbol)
  163. if len(symbolU) == 3 {
  164. symbolU += "CNY"
  165. }
  166. _, err = markinfo.SymbolId(symbolU)
  167. if err != nil {
  168. return "", err
  169. }
  170. var prefix string
  171. prefix = market.BtyPrefix
  172. myInsId := prefix + symbolU
  173. var iTE, iTS int64
  174. var bufferedCandles []client.Candle
  175. bufferedCandles, _ = clientDown.GetLastCandles(myInsId, periodId, 0x7fffffff)
  176. bufferedCandles = truncateBuffer(bufferedCandles, periodId, myInsId)
  177. var downN int
  178. var downTS int64
  179. switch action {
  180. case "init":
  181. if len(bufferedCandles) >= iCount {
  182. bufferedCandles = bufferedCandles[len(bufferedCandles)-iCount:]
  183. downN = 0
  184. downTS = 0
  185. } else {
  186. downN = -(iCount - len(bufferedCandles))
  187. downTS = -1
  188. }
  189. case "new":
  190. iTE, _ = strconv.ParseInt(te, 10, 64)
  191. iTE *= 1000
  192. beginTimeBuffered := int64(0x7fffffff)
  193. if len(bufferedCandles) > 0 {
  194. beginTimeBuffered = bufferedCandles[0].Timestamp
  195. }
  196. for cindex := 0; cindex < len(bufferedCandles); cindex++ {
  197. if bufferedCandles[cindex].Timestamp >= iTE {
  198. bufferedCandles = bufferedCandles[cindex:]
  199. break
  200. }
  201. }
  202. if beginTimeBuffered <= iTE {
  203. downN = 0
  204. downTS = 0
  205. if len(bufferedCandles) >= iCount {
  206. bufferedCandles = bufferedCandles[len(bufferedCandles)-iCount:]
  207. }
  208. } else {
  209. if len(bufferedCandles) >= iCount {
  210. bufferedCandles = bufferedCandles[len(bufferedCandles)-iCount:]
  211. downN = 0
  212. downTS = 0
  213. } else {
  214. if len(bufferedCandles) == 0 {
  215. downN = iCount
  216. downTS = iTE
  217. } else {
  218. downN = -(iCount - len(bufferedCandles))
  219. downTS = -1
  220. }
  221. }
  222. }
  223. case "down":
  224. iTS, _ = strconv.ParseInt(ts, 10, 64)
  225. iTS *= 1000
  226. for cindex := 0; cindex < len(bufferedCandles); cindex++ {
  227. if bufferedCandles[cindex].Timestamp > iTS {
  228. bufferedCandles = bufferedCandles[:cindex]
  229. break
  230. }
  231. }
  232. if len(bufferedCandles) >= iCount {
  233. bufferedCandles = bufferedCandles[len(bufferedCandles)-iCount:]
  234. downN = 0
  235. downTS = 0
  236. } else {
  237. if len(bufferedCandles) == 0 {
  238. downN = -iCount
  239. downTS = iTS
  240. } else {
  241. downN = -(iCount - len(bufferedCandles))
  242. downTS = -1
  243. }
  244. }
  245. }
  246. //log.Println("step2", len(bufferedCandles), downN, downTS)
  247. var filecandles []client.Candle
  248. _, filecandles, _ = clientDown.GetHistory(myInsId, periodId, downN, downTS)
  249. //log.Println("step3", len(filecandles))
  250. candles := make([]client.Candle, len(bufferedCandles)+len(filecandles))
  251. for findex := 0; findex <= 1; findex++ {
  252. if findex == 1 {
  253. for iBuf := 0; iBuf < len(bufferedCandles); iBuf++ {
  254. //bufferedCandles[iBuf] = changeCandle(bufferedCandles[iBuf], strings.ToUpper(period), strings.ToUpper(symbol))
  255. candles[len(filecandles)+iBuf] = bufferedCandles[iBuf]
  256. }
  257. } else {
  258. if downN < 0 {
  259. for iFile := len(filecandles) - 1; iFile >= 0; iFile-- {
  260. //filecandles[iFile] = changeCandle(filecandles[iFile], strings.ToUpper(period), strings.ToUpper(symbol))
  261. candles[len(filecandles)-iFile-1] = filecandles[iFile]
  262. }
  263. } else {
  264. for iFile := 0; iFile < len(filecandles); iFile++ {
  265. //filecandles[iFile] = changeCandle(filecandles[iFile], strings.ToUpper(period), strings.ToUpper(symbol))
  266. candles[iFile] = filecandles[iFile]
  267. }
  268. }
  269. }
  270. }
  271. var tData TData
  272. var kData KData
  273. if K_STYLE == style {
  274. kData.C = symbol
  275. kData.P = period
  276. kData.Action = action
  277. }
  278. if len(candles) >= iCount {
  279. if T_STYLE == style {
  280. tData.End = 0
  281. }
  282. if K_STYLE == style {
  283. kData.End = 0
  284. }
  285. } else {
  286. if T_STYLE == style {
  287. tData.End = 1
  288. }
  289. if K_STYLE == style {
  290. kData.End = 1
  291. }
  292. }
  293. if periodIdOld == market.M15 || periodIdOld == market.M30 ||
  294. periodIdOld == market.H2 || periodIdOld == market.H4 ||
  295. periodIdOld == market.W1 || periodIdOld == market.MN1 {
  296. candles = makeCandle(candles, periodIdOld, myInsId)
  297. }
  298. var candleLast client.Candle
  299. for cindex := 0; cindex < len(candles); cindex++ {
  300. if candles[cindex].Timestamp < candleLast.Timestamp {
  301. continue
  302. }
  303. bduplicated := false
  304. if candles[cindex].Timestamp == candleLast.Timestamp {
  305. bduplicated = true
  306. }
  307. if action == "down" && candles[cindex].Timestamp > iTS {
  308. break
  309. }
  310. if action == "new" && candles[cindex].Timestamp < iTE {
  311. continue
  312. }
  313. if candles[cindex].Open == 0 ||
  314. candles[cindex].High == 0 ||
  315. candles[cindex].Low == 0 ||
  316. candles[cindex].Close == 0 {
  317. candles[cindex] = candleLast
  318. }
  319. if bduplicated {
  320. if candleLast.RealVolums < candles[cindex].RealVolums {
  321. if T_STYLE == style {
  322. tData.Candles[len(tData.Candles)-1] = candles[cindex]
  323. }
  324. if K_STYLE == style {
  325. kData.Candles.X[len(kData.Candles.X)-1] = int(candles[cindex].Timestamp / 1000)
  326. kData.Candles.Y[len(kData.Candles.Y)-1] = [5]float32{float32(candles[cindex].Open), float32(candles[cindex].High), float32(candles[cindex].Low), float32(candles[cindex].Close), float32(candles[cindex].RealVolums)}
  327. kData.Volumes.X[len(kData.Volumes.X)-1] = int(candles[cindex].Timestamp / 1000)
  328. kData.Volumes.Y[len(kData.Volumes.Y)-1] = float32(candles[cindex].RealVolums)
  329. }
  330. candleLast = candles[cindex]
  331. }
  332. } else {
  333. if T_STYLE == style {
  334. tData.Candles = append(tData.Candles, candles[cindex])
  335. }
  336. if K_STYLE == style {
  337. kData.Candles.X = append(kData.Candles.X, int(candles[cindex].Timestamp/1000))
  338. kData.Candles.Y = append(kData.Candles.Y, [5]float32{float32(candles[cindex].Open), float32(candles[cindex].High), float32(candles[cindex].Low), float32(candles[cindex].Close), float32(candles[cindex].RealVolums)})
  339. kData.Volumes.X = append(kData.Volumes.X, int(candles[cindex].Timestamp/1000))
  340. kData.Volumes.Y = append(kData.Volumes.Y, float32(candles[cindex].RealVolums))
  341. }
  342. candleLast = candles[cindex]
  343. }
  344. }
  345. var dataLen int
  346. if T_STYLE == style {
  347. dataLen = len(tData.Candles)
  348. }
  349. if K_STYLE == style {
  350. dataLen = len(kData.Candles.X)
  351. }
  352. if dataLen >= iCount {
  353. if T_STYLE == style {
  354. tData.Candles = tData.Candles[dataLen-(iCount-1):]
  355. }
  356. if K_STYLE == style {
  357. kData.Candles.X = kData.Candles.X[dataLen-(iCount-1):]
  358. kData.Candles.Y = kData.Candles.Y[dataLen-(iCount-1):]
  359. kData.Volumes.X = kData.Volumes.X[dataLen-(iCount-1):]
  360. kData.Volumes.Y = kData.Volumes.Y[dataLen-(iCount-1):]
  361. }
  362. }
  363. var b []byte
  364. if K_STYLE == style {
  365. b, err = json.Marshal(&kData)
  366. }
  367. if T_STYLE == style {
  368. b, err = json.Marshal(&tData)
  369. }
  370. if err != nil {
  371. return "", errors.New("marshal error")
  372. }
  373. var output string
  374. if out == "jsonp" {
  375. output = fmt.Sprintf("if (%s) %s(%s)\n", cb, cb, string(b))
  376. } else {
  377. output = string(b)
  378. }
  379. return output, nil
  380. }
  381. func kdataHandler(w http.ResponseWriter, r *http.Request) {
  382. symbol := r.FormValue("c")
  383. period := r.FormValue("p")
  384. action := r.FormValue("action")
  385. count := r.FormValue("count")
  386. out := r.FormValue("out")
  387. cb := r.FormValue("callback")
  388. var ts, te string
  389. if action == "new" {
  390. te = r.FormValue("te")
  391. }
  392. if action == "down" {
  393. ts = r.FormValue("ts")
  394. }
  395. output, err := getData(symbol, period, action, count, out, cb, te, ts, K_STYLE)
  396. if err != nil {
  397. http.Error(w, err.Error(), http.StatusBadRequest)
  398. return
  399. }
  400. if out != "jsonp" {
  401. w.Header().Set("Access-Control-Allow-Origin", "*")
  402. w.Header().Add("Access-Control-Allow-Headers", "Content-Type")
  403. w.Header().Set("content-type", "application/json")
  404. }
  405. io.WriteString(w, output)
  406. }
  407. func tdataHandler(w http.ResponseWriter, r *http.Request) {
  408. symbol := r.FormValue("c")
  409. period := r.FormValue("p")
  410. action := r.FormValue("action")
  411. count := r.FormValue("count")
  412. out := r.FormValue("out")
  413. cb := r.FormValue("callback")
  414. var ts, te string
  415. if action == "new" {
  416. te = r.FormValue("te")
  417. }
  418. if action == "down" {
  419. ts = r.FormValue("ts")
  420. }
  421. output, err := getData(symbol, period, action, count, out, cb, te, ts, T_STYLE)
  422. if err != nil {
  423. http.Error(w, err.Error(), http.StatusBadRequest)
  424. return
  425. }
  426. if out != "jsonp" {
  427. w.Header().Set("Access-Control-Allow-Origin", "*")
  428. w.Header().Add("Access-Control-Allow-Headers", "Content-Type")
  429. w.Header().Set("content-type", "application/json")
  430. }
  431. io.WriteString(w, output)
  432. }
  433. func makeCandle(candles []client.Candle, periodIdOld int, insId string) []client.Candle {
  434. var candlestmp []market.Candle
  435. for _, v := range candles {
  436. candlestmp = append(candlestmp, market.Candle{
  437. Timestamp: v.Timestamp,
  438. Open: v.Open,
  439. High: v.High,
  440. Low: v.Low,
  441. Close: v.Close,
  442. RealVolums: v.RealVolums,
  443. TickVolums: v.TickVolums,
  444. })
  445. }
  446. r := market.NewCandleBuf(candlestmp)
  447. candlestmpnew, _ := market.ConvPeriod(r, insId, periodIdOld)
  448. candles = candles[0:0]
  449. for _, v := range candlestmpnew {
  450. candles = append(candles, client.Candle{
  451. Timestamp: v.Timestamp,
  452. Open: v.Open,
  453. High: v.High,
  454. Low: v.Low,
  455. Close: v.Close,
  456. RealVolums: v.RealVolums,
  457. TickVolums: v.TickVolums,
  458. })
  459. }
  460. return candles
  461. }
  462. func truncateBuffer(bufferedCandles []client.Candle, periodId int, insId string) []client.Candle {
  463. var filecandlelatesttime int64
  464. tmpDownN := -2
  465. var tmpfilecandles []client.Candle
  466. _, tmpfilecandles, _ = clientDown.GetHistory(insId, periodId, tmpDownN, -1)
  467. if len(tmpfilecandles) > 1 {
  468. filecandlelatesttime = tmpfilecandles[1].Timestamp
  469. /*if insId != "bty_BTYUSDT" && len(bufferedCandles) > 0 && bufferedCandles[0].Timestamp > tmpfilecandles[0].Timestamp {
  470. bufferedCandlesTmp := bufferedCandles[:]
  471. bufferedCandles = make([]client.Candle, len(bufferedCandlesTmp))
  472. for timestampAdded := tmpfilecandles[0].Timestamp + int64(periodId*1000); timestampAdded < bufferedCandlesTmp[0].Timestamp; timestampAdded += int64(periodId * 1000) {
  473. candleAdded := bufferedCandlesTmp[0]
  474. candleAdded.Timestamp = timestampAdded
  475. candleAdded.TickVolums = 0
  476. candleAdded.RealVolums = 0
  477. bufferedCandles = append(bufferedCandles, candleAdded)
  478. }
  479. bufferedCandles = append(bufferedCandles, bufferedCandlesTmp...)
  480. }*/
  481. var iPos int
  482. for iPos = 0; iPos < len(bufferedCandles); iPos++ {
  483. if bufferedCandles[iPos].Timestamp > filecandlelatesttime {
  484. break
  485. }
  486. }
  487. bufferedCandles = bufferedCandles[iPos:]
  488. }
  489. return bufferedCandles
  490. }
  491. func patchingByVolume(candles []client.Candle, periodId int, bAsc bool, bBuffered bool) []client.Candle {
  492. bNeeded := false
  493. for i := 0; i < len(candles); i++ {
  494. if candles[i].TickVolums == 0 {
  495. bNeeded = true
  496. break
  497. }
  498. }
  499. if bNeeded {
  500. var st, et int64
  501. var posHuobi int
  502. //var posOkCoin int
  503. if bAsc {
  504. st = candles[0].Timestamp
  505. et = candles[len(candles)-1].Timestamp
  506. } else {
  507. st = candles[len(candles)-1].Timestamp
  508. et = candles[0].Timestamp
  509. }
  510. var candlesHuobi []client.Candle
  511. if bBuffered {
  512. candlesHuobi, _ = clientDown.GetLastCandles("huobi_BTCCNY", periodId, 0x7fffffff)
  513. //candlesOkCoin, _ = clientDown.GetLastCandles("btc_BTCCNY", periodId, 0x7fffffff)
  514. } else {
  515. _, candlesHuobi, _ = clientDown.GetHistoryEx("huobi_BTCCNY", periodId, st, et)
  516. //_, candlesOkCoin, _ = clientDown.GetHistoryEx("btc_BTCCNY", periodId, st, et)
  517. }
  518. if bAsc {
  519. posHuobi = 0
  520. //posOkCoin = 0
  521. } else {
  522. posHuobi = len(candlesHuobi) - 1
  523. //posOkCoin = len(filecandlesOkCoin) - 1
  524. }
  525. candlesTmp := candles[:]
  526. candles = candles[0:0]
  527. for i := 0; i < len(candlesTmp); i++ {
  528. if candlesTmp[i].TickVolums == 0 {
  529. count := 0
  530. var candleHuobi client.Candle
  531. //var candleOkCoin client.Candle
  532. if bAsc {
  533. for j := posHuobi; j < len(candlesHuobi); j++ {
  534. if candlesHuobi[j].Timestamp == candlesTmp[i].Timestamp {
  535. posHuobi = j
  536. count++
  537. candleHuobi = candlesHuobi[j]
  538. break
  539. }
  540. if candlesHuobi[j].Timestamp > candlesTmp[i].Timestamp {
  541. posHuobi = j
  542. break
  543. }
  544. }
  545. /*for k := posOkCoin; k < len(filecandlesOkCoin); k++ {
  546. if filecandlesOkCoin[k].Timestamp == filecandlesTmp[i].Timestamp {
  547. posOkCoin = k
  548. count++
  549. candleOkCoin = filecandlesOkCoin[k]
  550. break
  551. }
  552. if filecandlesOkCoin[k].Timestamp > filecandlesTmp[i].Timestamp {
  553. posOkCoin = k
  554. break
  555. }
  556. }*/
  557. } else {
  558. for j := posHuobi; j >= 0; j-- {
  559. if candlesHuobi[j].Timestamp == candlesTmp[i].Timestamp {
  560. posHuobi = j
  561. count++
  562. candleHuobi = candlesHuobi[j]
  563. break
  564. }
  565. if candlesHuobi[j].Timestamp < candlesTmp[i].Timestamp {
  566. posHuobi = j
  567. break
  568. }
  569. }
  570. /*for k := posOkCoin; k >= 0; k-- {
  571. if filecandlesOkCoin[k].Timestamp == filecandlesTmp[i].Timestamp {
  572. posOkCoin = k
  573. count++
  574. candleOkCoin = filecandlesOkCoin[k]
  575. break
  576. }
  577. if filecandlesOkCoin[k].Timestamp < filecandlesTmp[i].Timestamp {
  578. posOkCoin = k
  579. break
  580. }
  581. }*/
  582. }
  583. if count > 0 {
  584. var candleComplex client.Candle
  585. count = 0
  586. if candleHuobi.Open > 0 && candleHuobi.High > 0 && candleHuobi.Low > 0 && candleHuobi.Close > 0 {
  587. count++
  588. candleComplex.Open += candleHuobi.Open
  589. candleComplex.High += candleHuobi.High
  590. candleComplex.Low += candleHuobi.Low
  591. candleComplex.Close += candleHuobi.Close
  592. }
  593. /*if candleOkCoin.Open > 0 && candleOkCoin.High > 0 && candleOkCoin.Low > 0 && candleOkCoin.Close > 0 {
  594. count++
  595. candleComplex.Open += candleOkCoin.Open
  596. candleComplex.High += candleOkCoin.High
  597. candleComplex.Low += candleOkCoin.Low
  598. candleComplex.Close += candleOkCoin.Close
  599. }*/
  600. //filecandles = append(filecandles, client.Candle{Timestamp: filecandlesTmp[i].Timestamp, Open: candleComplex.Open / float64(count),
  601. //High: candleComplex.High / float64(count), Low: candleComplex.Low / float64(count),
  602. //Close: candleComplex.Close / float64(count), RealVolums: (candleHuobi.TickVolums + candleOkCoin.TickVolums) * 150, TickVolums: (candleHuobi.TickVolums + candleOkCoin.TickVolums) / 2})
  603. candleHuobi.RealVolums /= 1e6
  604. candles = append(candles, candleHuobi)
  605. //log.Println("1", candleHuobi)
  606. } else {
  607. candles = append(candles, candlesTmp[i])
  608. //log.Println("2", candlesTmp[i])
  609. }
  610. } else {
  611. candles = append(candles, candlesTmp[i])
  612. //log.Println("3", candlesTmp[i])
  613. }
  614. }
  615. }
  616. return candles
  617. }
  618. func patchingByTime(candles []client.Candle, periodId int, bAsc bool) []client.Candle {
  619. bNeedAdd := false
  620. for i := 0; i < len(candles); i++ {
  621. if bAsc {
  622. if i > 0 && ((candles[i].Timestamp - candles[i-1].Timestamp) > int64(periodId*1000)) {
  623. bNeedAdd = true
  624. break
  625. }
  626. } else {
  627. if i > 0 && ((candles[i-1].Timestamp - candles[i].Timestamp) > int64(periodId*1000)) {
  628. bNeedAdd = true
  629. break
  630. }
  631. }
  632. }
  633. if bNeedAdd {
  634. candlesTmp := make([]client.Candle, len(candles))
  635. for k, v := range candles {
  636. candlesTmp[k] = v
  637. }
  638. candles = candles[0:0]
  639. for i := 0; i < len(candlesTmp); i++ {
  640. if bAsc {
  641. if i > 0 && ((candlesTmp[i].Timestamp - candlesTmp[i-1].Timestamp) > int64(periodId*1000)) {
  642. for timestampAdded := candlesTmp[i-1].Timestamp + int64(periodId*1000); timestampAdded < candlesTmp[i].Timestamp; timestampAdded += int64(periodId * 1000) {
  643. candleAdded := candlesTmp[i-1]
  644. candleAdded.Timestamp = timestampAdded
  645. candleAdded.TickVolums = 0
  646. candles = append(candles, candleAdded)
  647. }
  648. }
  649. } else {
  650. if i > 0 && ((candlesTmp[i-1].Timestamp - candlesTmp[i].Timestamp) > int64(periodId*1000)) {
  651. for timestampAdded := candlesTmp[i-1].Timestamp - int64(periodId*1000); timestampAdded > candlesTmp[i].Timestamp; timestampAdded -= int64(periodId * 1000) {
  652. candleAdded := candlesTmp[i-1]
  653. candleAdded.Timestamp = timestampAdded
  654. candleAdded.TickVolums = 0
  655. candles = append(candles, candleAdded)
  656. }
  657. }
  658. }
  659. candles = append(candles, candlesTmp[i])
  660. }
  661. }
  662. return candles
  663. }
  664. type gzipResponseWriter struct {
  665. io.Writer
  666. http.ResponseWriter
  667. }
  668. func (w gzipResponseWriter) Write(b []byte) (int, error) {
  669. return w.Writer.Write(b)
  670. }
  671. func (w gzipResponseWriter) Flush() {
  672. w.Writer.(*gzip.Writer).Flush()
  673. w.ResponseWriter.(http.Flusher).Flush()
  674. }
  675. func makeGzipHandler(fn http.HandlerFunc) http.HandlerFunc {
  676. return func(w http.ResponseWriter, r *http.Request) {
  677. if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
  678. fn(w, r)
  679. return
  680. }
  681. w.Header().Set("Content-Encoding", "gzip")
  682. w.Header().Set("Content-Type", "text/javascript")
  683. gz := gzip.NewWriter(w)
  684. defer gz.Close()
  685. fn(gzipResponseWriter{Writer: gz, ResponseWriter: w}, r)
  686. }
  687. }
  688. func main() {
  689. runtime.GOMAXPROCS(runtime.NumCPU())
  690. conf, err := readConf()
  691. if err != nil {
  692. flag.Parse()
  693. } else {
  694. *saddr1 = conf.Saddr1
  695. *saddr2 = conf.Saddr2
  696. *saddr3 = conf.Saddr3
  697. *saddr4 = conf.Saddr4
  698. }
  699. err = connectServer()
  700. if err != nil {
  701. log.Fatal("connect server", err)
  702. }
  703. s := &http.Server{
  704. //Addr: ":3062",
  705. Addr: ":4062",
  706. //Addr: ":9062",
  707. ReadTimeout: 10 * time.Second,
  708. WriteTimeout: 10 * time.Second,
  709. MaxHeaderBytes: 1 << 20,
  710. }
  711. http.HandleFunc("/kdata", makeGzipHandler(kdataHandler))
  712. http.HandleFunc("/tdata", makeGzipHandler(tdataHandler))
  713. log.Fatal(s.ListenAndServeTLS("214341259320977.pem", "214341259320977.key"))
  714. //log.Fatal(s.ListenAndServe())
  715. //log.Fatal(s.ListenAndServeTLS("licai20170620.pem", "licai20170620.key"))
  716. }