main.go 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184
  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. "os"
  13. "runtime"
  14. "strconv"
  15. "strings"
  16. "sync"
  17. "time"
  18. "tickserver/client"
  19. "tickserver/framework/base"
  20. "tickserver/markinfo"
  21. "tickserver/server/market"
  22. )
  23. type RealTick struct {
  24. tg base.TickGo
  25. //tgCh <-chan base.TickGo
  26. now int64
  27. }
  28. type Options struct {
  29. Start int `json:"start"`
  30. End int `json:"end"`
  31. Total int `json:"total_size"`
  32. }
  33. type KCandle struct {
  34. X []int `json:"x"`
  35. Y [][5]float32 `json:"y"`
  36. }
  37. type KVolume struct {
  38. X []int `json:"x"`
  39. Y []int `json:"y"`
  40. }
  41. type KData struct {
  42. C string `json:"c"`
  43. P string `json:"p"`
  44. Action string `json:"action"`
  45. KOptions Options `json:"options"`
  46. Candles KCandle `json:"main"`
  47. Volumes KVolume `json:"volumes|||__ignore__"`
  48. }
  49. type HistoryData struct {
  50. C string `json:"c"`
  51. P string `json:"p"`
  52. Action string `json:"action"`
  53. End int64 `json:"end"`
  54. MainData [][6]string `json:"main"`
  55. Easyforex [][6]string `json:"easyforex"`
  56. Oanda [][6]string `json:"oanda"`
  57. }
  58. type SymbolData struct {
  59. Unit float64
  60. PriceIncrement float64
  61. Symbol int
  62. Name string
  63. }
  64. //type byDlInfo []market.DlInfo
  65. //func (a byDlInfo) Len() int { return len(a) }
  66. //func (a byDlInfo) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
  67. //func (a byDlInfo) Less(i, j int) bool { return a[i].Reply.St < a[j].Reply.St }
  68. var saddr1 = flag.String("s1", "127.0.0.1:19528", "tick server address 1") //115.231.103.7
  69. var saddr2 = flag.String("s2", "127.0.0.1:19528", "tick server address 2") //127.0.0.1
  70. var saddr3 = flag.String("s3", "127.0.0.1:19529", "tick server address 3") //115.236.75.194
  71. var saddr4 = flag.String("s4", "127.0.0.1:9090", "tick server address 4") //19528 9090
  72. var clientSub *client.ClientSimple
  73. var clientDown *client.ClientSimple
  74. var tkMap = make(map[string]base.TickGo)
  75. var tkMutex sync.Mutex
  76. type Conf struct {
  77. Saddr1 string //
  78. Saddr2 string //
  79. Saddr3 string //
  80. Saddr4 string
  81. }
  82. type SpecialTick struct {
  83. Timestamp int64 `json:"ts"`
  84. Open float64 `json:"open"`
  85. High float64 `json:"high"`
  86. Low float64 `json:"low"`
  87. Last float64 `json:"last"`
  88. Volume float64 `json:"volume"`
  89. }
  90. type StringSpecialTick struct {
  91. Timestamp string `json:"ts"`
  92. Open string `json:"open"`
  93. High string `json:"high"`
  94. Low string `json:"low"`
  95. Last string `json:"last"`
  96. Volume string `json:"volume"`
  97. }
  98. func readConf() (*Conf, error) {
  99. f, err := os.Open("webproxy.json")
  100. if err != nil {
  101. return nil, err
  102. }
  103. defer f.Close()
  104. dec := json.NewDecoder(f)
  105. conf := &Conf{}
  106. err = dec.Decode(conf)
  107. if err != nil {
  108. return nil, err
  109. }
  110. return conf, nil
  111. }
  112. func getStringSTK(stk SpecialTick, insId string) StringSpecialTick {
  113. sstk := StringSpecialTick{
  114. Timestamp: fmt.Sprintf("%d", stk.Timestamp),
  115. Open: fmt.Sprintf("%.4f", stk.Open),
  116. }
  117. switch insId {
  118. case "bty_BCCBTC":
  119. sstk.Last = fmt.Sprintf("%.4f", stk.Last)
  120. sstk.High = fmt.Sprintf("%.4f", stk.High)
  121. sstk.Low = fmt.Sprintf("%.4f", stk.Low)
  122. sstk.Volume = fmt.Sprintf("%.4f", stk.Volume)
  123. case "bty_ETHBTC":
  124. sstk.Last = fmt.Sprintf("%.5f", stk.Last)
  125. sstk.High = fmt.Sprintf("%.5f", stk.High)
  126. sstk.Low = fmt.Sprintf("%.5f", stk.Low)
  127. sstk.Volume = fmt.Sprintf("%.3f", stk.Volume)
  128. case "bty_ETCBTC":
  129. sstk.Last = fmt.Sprintf("%.6f", stk.Last)
  130. sstk.High = fmt.Sprintf("%.6f", stk.High)
  131. sstk.Low = fmt.Sprintf("%.6f", stk.Low)
  132. sstk.Volume = fmt.Sprintf("%.2f", stk.Volume)
  133. case "bty_ZECBTC":
  134. sstk.Last = fmt.Sprintf("%.5f", stk.Last)
  135. sstk.High = fmt.Sprintf("%.5f", stk.High)
  136. sstk.Low = fmt.Sprintf("%.5f", stk.Low)
  137. sstk.Volume = fmt.Sprintf("%.3f", stk.Volume)
  138. case "bty_LTCBTC":
  139. sstk.Last = fmt.Sprintf("%.6f", stk.Last)
  140. sstk.High = fmt.Sprintf("%.6f", stk.High)
  141. sstk.Low = fmt.Sprintf("%.6f", stk.Low)
  142. sstk.Volume = fmt.Sprintf("%.2f", stk.Volume)
  143. case "bty_BTCUSDT":
  144. sstk.Last = fmt.Sprintf("%.2f", stk.Last)
  145. sstk.High = fmt.Sprintf("%.2f", stk.High)
  146. sstk.Low = fmt.Sprintf("%.2f", stk.Low)
  147. sstk.Volume = fmt.Sprintf("%.4f", stk.Volume)
  148. case "bty_BCCUSDT":
  149. sstk.Last = fmt.Sprintf("%.2f", stk.Last)
  150. sstk.High = fmt.Sprintf("%.2f", stk.High)
  151. sstk.Low = fmt.Sprintf("%.2f", stk.Low)
  152. sstk.Volume = fmt.Sprintf("%.4f", stk.Volume)
  153. case "bty_ETHUSDT":
  154. sstk.Last = fmt.Sprintf("%.2f", stk.Last)
  155. sstk.High = fmt.Sprintf("%.2f", stk.High)
  156. sstk.Low = fmt.Sprintf("%.2f", stk.Low)
  157. sstk.Volume = fmt.Sprintf("%.3f", stk.Volume)
  158. case "bty_ETCUSDT":
  159. sstk.Last = fmt.Sprintf("%.2f", stk.Last)
  160. sstk.High = fmt.Sprintf("%.2f", stk.High)
  161. sstk.Low = fmt.Sprintf("%.2f", stk.Low)
  162. sstk.Volume = fmt.Sprintf("%.2f", stk.Volume)
  163. case "bty_ZECUSDT":
  164. sstk.Last = fmt.Sprintf("%.2f", stk.Last)
  165. sstk.High = fmt.Sprintf("%.2f", stk.High)
  166. sstk.Low = fmt.Sprintf("%.2f", stk.Low)
  167. sstk.Volume = fmt.Sprintf("%.3f", stk.Volume)
  168. case "bty_LTCUSDT":
  169. sstk.Last = fmt.Sprintf("%.2f", stk.Last)
  170. sstk.High = fmt.Sprintf("%.2f", stk.High)
  171. sstk.Low = fmt.Sprintf("%.2f", stk.Low)
  172. sstk.Volume = fmt.Sprintf("%.2f", stk.Volume)
  173. case "bty_YCCUSDT":
  174. fallthrough
  175. case "bty_BTYUSDT":
  176. sstk.Last = fmt.Sprintf("%.4f", stk.Last)
  177. sstk.High = fmt.Sprintf("%.4f", stk.High)
  178. sstk.Low = fmt.Sprintf("%.4f", stk.Low)
  179. sstk.Volume = fmt.Sprintf("%.1f", stk.Volume)
  180. case "bty_BTCSUSDT":
  181. sstk.Last = fmt.Sprintf("%.2f", stk.Last)
  182. sstk.High = fmt.Sprintf("%.2f", stk.High)
  183. sstk.Low = fmt.Sprintf("%.2f", stk.Low)
  184. sstk.Volume = fmt.Sprintf("%.2f", stk.Volume)
  185. case "bty_SCUSDT":
  186. sstk.Last = fmt.Sprintf("%.6f", stk.Last)
  187. sstk.High = fmt.Sprintf("%.6f", stk.High)
  188. sstk.Low = fmt.Sprintf("%.6f", stk.Low)
  189. sstk.Volume = fmt.Sprintf("%.0f", stk.Volume)
  190. case "bty_BTSUSDT":
  191. sstk.Last = fmt.Sprintf("%.4f", stk.Last)
  192. sstk.High = fmt.Sprintf("%.4f", stk.High)
  193. sstk.Low = fmt.Sprintf("%.4f", stk.Low)
  194. sstk.Volume = fmt.Sprintf("%.2f", stk.Volume)
  195. case "bty_DCRUSDT":
  196. sstk.Last = fmt.Sprintf("%.2f", stk.Last)
  197. sstk.High = fmt.Sprintf("%.2f", stk.High)
  198. sstk.Low = fmt.Sprintf("%.2f", stk.Low)
  199. sstk.Volume = fmt.Sprintf("%.2f", stk.Volume)
  200. default:
  201. }
  202. return sstk
  203. }
  204. func dayHandler(w http.ResponseWriter, r *http.Request) {
  205. //cb := r.FormValue("callback")
  206. typ := r.FormValue("type")
  207. symbol := r.FormValue("symbol")
  208. //log.Println(cb, typ, symbol)
  209. insId := typ + "_" + symbol
  210. candles, err := clientDown.GetLastCandles(insId, market.D1, 1)
  211. if err != nil {
  212. http.Error(w, "server get data failed", http.StatusInternalServerError)
  213. return
  214. }
  215. if len(candles) == 0 {
  216. _, candles, _ = clientDown.GetHistory(insId, market.D1, -1, -1)
  217. }
  218. if len(candles) == 0 {
  219. http.Error(w, "server get data failed", http.StatusInternalServerError)
  220. return
  221. }
  222. stk := SpecialTick{Timestamp: candles[0].Timestamp / 1000, Open: candles[0].Open, High: candles[0].High,
  223. Low: candles[0].Low, Last: candles[0].Close, Volume: candles[0].RealVolums}
  224. sstk := getStringSTK(stk, insId)
  225. b, err := json.Marshal(&sstk)
  226. if err != nil {
  227. http.Error(w, "json encoding error", http.StatusInternalServerError)
  228. return
  229. }
  230. w.Header().Set("Access-Control-Allow-Origin", "*")
  231. w.Header().Add("Access-Control-Allow-Headers", "Content-Type")
  232. w.Header().Set("content-type", "application/json")
  233. io.WriteString(w, string(b))
  234. }
  235. func h24Handler(w http.ResponseWriter, r *http.Request) {
  236. //cb := r.FormValue("callback")
  237. typ := r.FormValue("type")
  238. symbol := r.FormValue("symbol")
  239. //log.Println(cb, typ, symbol)
  240. var candles []client.Candle
  241. insId := typ + "_" + symbol
  242. bufcandles, err := clientDown.GetLastCandles(insId, market.H1, 24)
  243. if err != nil {
  244. http.Error(w, "server get data failed", http.StatusInternalServerError)
  245. return
  246. } else {
  247. //fmt.Println("h24 1", len(bufcandles), bufcandles[0], bufcandles[len(bufcandles)-1])
  248. if len(bufcandles) < 24 {
  249. _, filecandles, _ := clientDown.GetHistory(insId, market.H1, -24, -1)
  250. //fmt.Println("h24 2", len(filecandles), filecandles[0], filecandles[len(filecandles)-1])
  251. var candlesDesc []client.Candle
  252. var bufCandleTime int64
  253. if len(bufcandles) > 0 {
  254. bufCandleTime = bufcandles[0].Timestamp
  255. }
  256. for i := 0; i < len(filecandles); i++ {
  257. if filecandles[i].Timestamp < bufCandleTime {
  258. candlesDesc = append(candlesDesc, filecandles[i])
  259. }
  260. if len(candlesDesc) >= (24 - len(bufcandles)) {
  261. break
  262. }
  263. }
  264. for i := len(candlesDesc) - 1; i >= 0; i-- {
  265. candles = append(candles, candlesDesc[i])
  266. }
  267. //fmt.Println("h24 3", len(candles), candles[0], candles[len(candles)-1])
  268. candles = append(candles, bufcandles[:]...)
  269. //fmt.Println("h24 4", len(candles), candles[0], candles[len(candles)-1])
  270. } else {
  271. candles = bufcandles[:]
  272. }
  273. var stk SpecialTick
  274. if len(candles) > 0 {
  275. stk.Low = candles[0].Low
  276. stk.Open = candles[0].Open
  277. stk.Timestamp = candles[0].Timestamp / 1000
  278. for i := 0; i < len(candles); i++ {
  279. //fmt.Println("h24 5", i, candles[i])
  280. stk.Volume += candles[i].RealVolums
  281. if candles[i].High > stk.High {
  282. stk.High = candles[i].High
  283. }
  284. if candles[i].Low < stk.Low {
  285. stk.Low = candles[i].Low
  286. }
  287. stk.Last = candles[i].Close
  288. }
  289. }
  290. sstk := getStringSTK(stk, insId)
  291. b, err := json.Marshal(&sstk)
  292. if err != nil {
  293. http.Error(w, "json encoding error", http.StatusInternalServerError)
  294. return
  295. }
  296. w.Header().Set("Access-Control-Allow-Origin", "*")
  297. w.Header().Add("Access-Control-Allow-Headers", "Content-Type")
  298. w.Header().Set("content-type", "application/json")
  299. io.WriteString(w, string(b))
  300. }
  301. }
  302. func subTick(insId string, symbolId int16) error {
  303. ins := clientSub.GetIns(insId)
  304. if ins == nil {
  305. errinfo := fmt.Sprintf("instrument %s not supported.", insId)
  306. return errors.New(errinfo)
  307. }
  308. clientSub.SubMarket(insId)
  309. ins.OnMarket().Attach(func(v interface{}) error {
  310. m, ok := v.(*client.Market)
  311. if !ok {
  312. //log.Println("v.(*Market) is NOT ok", insId)
  313. err := errors.New("v.(*Market) is NOT ok")
  314. return err
  315. }
  316. if m.InsId != insId {
  317. //log.Println("m.InsId != insId", m.InsId, insId)
  318. err := errors.New("v.(*Market) insid is NOT ok")
  319. return err
  320. }
  321. //log.Println("@@@:Market:", m)
  322. //now := time.Now()
  323. //timestampNow := now.Unix()*1000 + int64(now.Nanosecond())/1000000
  324. //log.Println("query", timestampNow, m.Timestamp, timestampNow-m.Timestamp)
  325. var tg base.TickGo
  326. tg.Time = int32(m.Timestamp / 1000)
  327. tg.Ms = int16(m.Timestamp % 1000)
  328. tg.Symbol = symbolId
  329. tg.Ask = float32(m.LastPrice)
  330. tg.Bid = float32(m.LastPrice)
  331. tg.Askv = float32(m.Volume)
  332. tg.Bidv = float32(m.Volume)
  333. if tg.Ask != 0. && tg.Bid != 0. {
  334. tkMutex.Lock()
  335. tkMap[insId] = tg
  336. tkMutex.Unlock()
  337. } else {
  338. //log.Println("value of ask or bid is 0", tg)
  339. }
  340. //log.Println(tg)
  341. return nil
  342. })
  343. return nil
  344. }
  345. func getOutput(cb string, ticks []base.TickGo) (output string) {
  346. b, err := json.Marshal(ticks)
  347. if err != nil {
  348. //log.Println(err)
  349. }
  350. output = fmt.Sprintf("if (%s) %s(%s)\n", cb, cb, string(b))
  351. return output
  352. }
  353. func connectServer() (err error) {
  354. clientSub, err = client.NewClientSimple(*saddr1, *saddr2, *saddr3, *saddr4, "./tmp")
  355. if err != nil {
  356. //log.Println("new client", err)
  357. return err
  358. }
  359. //insMap := clientSub.GetInsMap()
  360. //for insId, ins := range insMap {
  361. //log.Println(insId, ins)
  362. //}
  363. clientDown, err = client.NewClientSimple(*saddr1, *saddr2, *saddr3, *saddr4, "./tmp")
  364. if err != nil {
  365. //log.Println("new client", err)
  366. return err
  367. }
  368. return nil
  369. }
  370. func tickHandler(w http.ResponseWriter, r *http.Request) {
  371. //log.Println(r)
  372. //_, ok := w.(http.Hijacker)
  373. //if !ok {
  374. //http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError)
  375. //return
  376. //} else {
  377. //}
  378. cb := r.FormValue("callback")
  379. typ := r.FormValue("type")
  380. symbol := r.FormValue("symbol")
  381. //log.Println(cb, typ, symbol)
  382. symbols := make([]string, 0)
  383. if symbol == "" {
  384. insMap := clientSub.GetInsMap()
  385. for _, v := range insMap {
  386. insTyp := strings.Split(v.Id, "_")[0]
  387. insSymbol := strings.Split(v.Id, "_")[1]
  388. if insTyp == typ {
  389. if typ == "lmax" {
  390. bookId, err := strconv.Atoi(insSymbol)
  391. if err != nil {
  392. continue
  393. }
  394. symbolId, err := markinfo.BookIdToSymbolId(bookId)
  395. if err != nil {
  396. continue
  397. }
  398. insSymbol, err = markinfo.SymbolName(symbolId)
  399. if err != nil {
  400. continue
  401. }
  402. }
  403. symbols = append(symbols, insSymbol)
  404. }
  405. }
  406. } else {
  407. symbols = strings.Split(symbol, ",")
  408. }
  409. ticks := make([]base.TickGo, 0)
  410. for _, v := range symbols {
  411. symbolId, err := markinfo.SymbolId(v)
  412. if err != nil {
  413. if typ == "lmax" && v == "CRUDE" {
  414. symbolId = markinfo.OILUSD
  415. } // else {
  416. //http.Error(w, "webserver doesn't support symbol", http.StatusBadRequest)
  417. //return
  418. //}
  419. }
  420. myInsId := typ + "_" + v
  421. if typ == "lmax" {
  422. lmaxId, err := markinfo.SymbolIdToBookId(symbolId)
  423. if err != nil {
  424. if typ == "lmax" && (v == "CRUDE" || v == "OILUSD") {
  425. lmaxId = 100800
  426. } else {
  427. http.Error(w, "webserver doesn't support symbol", http.StatusBadRequest)
  428. return
  429. }
  430. }
  431. slmaxId := fmt.Sprintf("%d", lmaxId)
  432. myInsId = typ + "_" + slmaxId
  433. }
  434. tkMutex.Lock()
  435. tick, ok := tkMap[myInsId]
  436. tkMutex.Unlock()
  437. if ok {
  438. /*if typ == "lmax" {
  439. tick.Time = int32(time.Now().Unix())
  440. tick.Ms = 0
  441. }*/
  442. ticks = append(ticks, tick)
  443. } else {
  444. /*if typ == "lmax" {
  445. tmpticks, err := clientSub.GetTickHistory(myInsId, -1, -1)
  446. if len(tmpticks) > 0 {
  447. tick.Time = int32(time.Now().Unix()) //int32(tmpticks[0].Timestamp / 1000)
  448. tick.Ms = 0 //int16(tmpticks[0].Timestamp % 1000)
  449. tick.Symbol = int16(symbolId)
  450. tick.Ask = float32(tmpticks[0].Price)
  451. tick.Bid = float32(tmpticks[0].Price)
  452. tick.Askv = int32(tmpticks[0].Volume)
  453. tick.Bidv = int32(tmpticks[0].Volume)
  454. ticks = append(ticks, tick)
  455. tkMutex.Lock()
  456. tkMap[myInsId] = tick
  457. tkMutex.Unlock()
  458. }
  459. log.Println("fuck", err, len(tmpticks))
  460. }*/
  461. err := subTick(myInsId, int16(symbolId))
  462. if err != nil {
  463. //log.Println(err)
  464. }
  465. }
  466. }
  467. output := getOutput(cb, ticks)
  468. io.WriteString(w, output)
  469. }
  470. func getDownOutput(cb string, hisData *HistoryData) (output string) {
  471. b, err := json.Marshal(hisData)
  472. if err != nil {
  473. //log.Println(err)
  474. }
  475. if len(cb) > 0 {
  476. output = fmt.Sprintf("if (%s) %s(%s)\n", cb, cb, string(b))
  477. } else {
  478. output = string(b) + "\n"
  479. }
  480. return output
  481. }
  482. func candle2Str(candle market.Candle) [6]string {
  483. var candleStrings [6]string
  484. candleStrings[0] = fmt.Sprintf("%d", candle.Timestamp/1000)
  485. candleStrings[1] = fmt.Sprintf("%f", candle.Open)
  486. candleStrings[2] = fmt.Sprintf("%f", candle.High)
  487. candleStrings[3] = fmt.Sprintf("%f", candle.Low)
  488. candleStrings[4] = fmt.Sprintf("%f", candle.Close)
  489. candleStrings[5] = fmt.Sprintf("%d", 0)
  490. return candleStrings
  491. }
  492. func downHandler(w http.ResponseWriter, r *http.Request) {
  493. symbol := r.FormValue("c")
  494. period := r.FormValue("p")
  495. action := r.FormValue("action")
  496. count := r.FormValue("count")
  497. typ := r.FormValue("type")
  498. //out := r.FormValue("out")
  499. cb := r.FormValue("callback")
  500. var ts, te string
  501. if action == "new" {
  502. te = r.FormValue("te")
  503. }
  504. if action == "down" {
  505. ts = r.FormValue("ts")
  506. }
  507. //log.Println(symbol, period, action, count, typ, out, te, ts)
  508. symbolId, err := markinfo.SymbolId(symbol)
  509. if err != nil {
  510. if symbol == "CRUDE" {
  511. symbolId = markinfo.OILUSD
  512. } else {
  513. http.Error(w, "webserver doesn't support symbol", http.StatusBadRequest)
  514. return
  515. }
  516. }
  517. periodId, ok := market.PeriodIdMap[period]
  518. if !ok {
  519. http.Error(w, "webserver doesn't support period", http.StatusBadRequest)
  520. return
  521. }
  522. iCount, err := strconv.Atoi(count)
  523. if action != "new" && err != nil {
  524. http.Error(w, "webserver doesn't support count", http.StatusBadRequest)
  525. return
  526. }
  527. types := strings.Split(typ, "|")
  528. for i, v := range types {
  529. if v == "main" {
  530. types[i] = types[0]
  531. types[0] = v
  532. break
  533. }
  534. }
  535. typeCount := len(types)
  536. done := make(chan bool, typeCount)
  537. endCh := make(chan int64, typeCount-1)
  538. var hisData HistoryData
  539. hisData.C = symbol
  540. hisData.P = period
  541. hisData.Action = action
  542. var mainTimestamps []int64
  543. var easyforexCandles, oandaCandles []client.Candle
  544. easyforexTimestampMap := make(map[int64]int)
  545. oandaTimestampMap := make(map[int64]int)
  546. //log.Println("test", types)
  547. for i := 0; i < typeCount; i++ {
  548. v := types[i]
  549. //for i, v := range types {
  550. var prefix string
  551. switch v {
  552. case "main":
  553. prefix = market.LmaxPrefix
  554. if symbol == "BTCCNY" || symbol == "BTCUSD" || symbol == "BTCFUSD" {
  555. prefix = market.BtcPrefix
  556. } else if symbol == "BTCETH" {
  557. prefix = market.PoloPrefix
  558. } else if symbol == "ETHCNY" || symbol == "BTYCNY" || symbol == "ETCCNY" {
  559. prefix = market.BtyPrefix
  560. }
  561. case "easyforex":
  562. prefix = market.EasyForexPrefix
  563. if symbol == "CRUDE" {
  564. symbol = "OILUSD"
  565. }
  566. case "oanda":
  567. prefix = market.OandaPrefix
  568. if symbol == "CRUDE" {
  569. symbol = "OILUSD"
  570. }
  571. }
  572. myInsId := prefix + symbol
  573. if prefix == market.LmaxPrefix {
  574. lmaxId, err := markinfo.SymbolIdToBookId(symbolId)
  575. if err != nil {
  576. if symbolId == markinfo.OILUSD {
  577. lmaxId = 100800
  578. } else {
  579. http.Error(w, "webserver doesn't support symbol", http.StatusBadRequest)
  580. return
  581. }
  582. }
  583. slmaxId := fmt.Sprintf("%d", lmaxId)
  584. myInsId = market.LmaxPrefix + slmaxId
  585. }
  586. go func() {
  587. var end, iTE, iTS int64
  588. var bufferedCandlesDesc []client.Candle
  589. var downN int
  590. var downTS int64
  591. switch action {
  592. case "init":
  593. bufferedCandlesAsc, _ := clientDown.GetLastCandles(myInsId, periodId, 0x7fffffff)
  594. for cindex := len(bufferedCandlesAsc) - 1; cindex >= 0; cindex-- {
  595. bufferedCandlesDesc = append(bufferedCandlesDesc, bufferedCandlesAsc[cindex])
  596. if len(bufferedCandlesDesc) >= iCount {
  597. break
  598. }
  599. }
  600. downN = -(iCount - len(bufferedCandlesDesc))
  601. downTS = -1
  602. case "new":
  603. iCount = 1000
  604. iTE, _ = strconv.ParseInt(te, 10, 64)
  605. iTE *= 1000
  606. bufferedCandlesAsc, _ := clientDown.GetLastCandles(myInsId, periodId, 0x7fffffff)
  607. //log.Println("haha.....", myInsId, bufferedCandlesAsc)
  608. for cindex := len(bufferedCandlesAsc) - 1; cindex >= 0; cindex-- {
  609. if bufferedCandlesAsc[cindex].Timestamp >= iTE {
  610. bufferedCandlesDesc = append(bufferedCandlesDesc, bufferedCandlesAsc[cindex])
  611. if len(bufferedCandlesDesc) >= iCount {
  612. break
  613. }
  614. }
  615. }
  616. if len(bufferedCandlesDesc) > 0 {
  617. downN = -(iCount - len(bufferedCandlesDesc))
  618. downTS = -1
  619. } else {
  620. downN = iCount
  621. downTS = iTE
  622. }
  623. case "down":
  624. iTS, _ = strconv.ParseInt(ts, 10, 64)
  625. iTS *= 1000
  626. tmpBufferedCandles, _ := clientDown.GetLastCandles(myInsId, periodId, 1)
  627. if len(tmpBufferedCandles) > 0 && tmpBufferedCandles[0].Timestamp <= iTS {
  628. bufferedCandlesAsc, _ := clientDown.GetLastCandles(myInsId, periodId, 0x7fffffff)
  629. for cindex := len(bufferedCandlesAsc) - 1; cindex >= 0; cindex-- {
  630. if bufferedCandlesAsc[cindex].Timestamp <= iTS {
  631. bufferedCandlesDesc = append(bufferedCandlesDesc, bufferedCandlesAsc[cindex])
  632. if len(bufferedCandlesDesc) >= iCount {
  633. break
  634. }
  635. }
  636. }
  637. }
  638. if len(bufferedCandlesDesc) > 0 {
  639. downN = -(iCount - len(bufferedCandlesDesc))
  640. downTS = -1
  641. } else {
  642. downN = -iCount
  643. downTS = iTS
  644. }
  645. }
  646. //log.Println(myInsId, len(bufferedCandlesDesc))
  647. //for _, candle := range bufferedCandlesDesc {
  648. //log.Println(candle)
  649. //}
  650. //log.Println("test", myInsId, periodId, downN, downTS, false)
  651. _, filecandles, _ := clientDown.GetHistory(myInsId, periodId, downN, downTS)
  652. //log.Println("test", myInsId, len(fileticks), len(filecandles))
  653. if v != "main" {
  654. end = <-endCh
  655. }
  656. bEnd := false
  657. var timestampLast int64
  658. timestampLast = 0x7fffffffffffffff
  659. for findex := 1; findex >= 0; findex-- {
  660. var candles []client.Candle
  661. if findex == 1 {
  662. //candles = append(candles, bufferedCandlesDesc...)
  663. for iBuffered := len(bufferedCandlesDesc) - 1; iBuffered >= 0; iBuffered-- {
  664. candles = append(candles, bufferedCandlesDesc[iBuffered])
  665. }
  666. if v == "oanda" {
  667. //for _, vtmp := range candles {
  668. //log.Println("test1", vtmp)
  669. //}
  670. }
  671. //log.Println("buf", v, len(candles))
  672. } else {
  673. if downN < 0 {
  674. for iFile := len(filecandles) - 1; iFile >= 0; iFile-- {
  675. candles = append(candles, filecandles[iFile])
  676. }
  677. } else {
  678. candles = filecandles[:]
  679. }
  680. if v == "oanda" {
  681. //for _, vtmp := range candles {
  682. //log.Println("test2", vtmp)
  683. //}
  684. }
  685. //log.Println("file", v, len(candles), fnames[findex].Fname)
  686. }
  687. //log.Println("aaaa", v, candles)
  688. for cindex := len(candles) - 1; cindex >= 0; cindex-- {
  689. if v == "main" && periodId == market.D1 {
  690. tmpTime := time.Unix(candles[cindex].Timestamp/1000, 0)
  691. if tmpTime.Hour() != 0 || tmpTime.Minute() != 0 || tmpTime.Second() != 0 {
  692. //log.Println("data time not standard", v, tmpTime)
  693. //candles[cindex].Timestamp -= (int64(tmpTime.Hour())*3600 + int64(tmpTime.Minute())*60 + int64(tmpTime.Second())) * 1000
  694. }
  695. }
  696. if candles[cindex].Timestamp >= timestampLast {
  697. continue
  698. }
  699. timestampLast = candles[cindex].Timestamp
  700. if action == "down" && candles[cindex].Timestamp > iTS {
  701. continue
  702. }
  703. if action == "new" && candles[cindex].Timestamp < iTE {
  704. continue
  705. }
  706. if v == "main" {
  707. var candleStrings [6]string
  708. candleStrings[0] = fmt.Sprintf("%d", candles[cindex].Timestamp/1000)
  709. candleStrings[1] = fmt.Sprintf("%f", candles[cindex].Open)
  710. candleStrings[2] = fmt.Sprintf("%f", candles[cindex].High)
  711. candleStrings[3] = fmt.Sprintf("%f", candles[cindex].Low)
  712. candleStrings[4] = fmt.Sprintf("%f", candles[cindex].Close)
  713. candleStrings[5] = fmt.Sprintf("%d", 0)
  714. hisData.MainData = append(hisData.MainData, candleStrings)
  715. end = candles[cindex].Timestamp
  716. mainTimestamps = append(mainTimestamps, end)
  717. //tmpTime := time.Unix(end/1000, 0)
  718. //if tmpTime.Hour() != 0 || tmpTime.Minute() != 0 || tmpTime.Second() != 0 {
  719. //log.Println("data error", v, tmpTime)
  720. //}
  721. if len(hisData.MainData) >= iCount {
  722. bEnd = true
  723. //log.Println("test", v, len(hisData.MainData))
  724. break
  725. }
  726. } else {
  727. if candles[cindex].Timestamp < end {
  728. bEnd = true
  729. if v == "oanda" {
  730. //log.Println("test", v, end, candles[cindex].Timestamp, len(hisData.Oanda))
  731. }
  732. if v == "easyforex" {
  733. //log.Println("test", v, end, candles[cindex].Timestamp, len(hisData.Easyforex))
  734. }
  735. break
  736. }
  737. if v == "easyforex" {
  738. //hisData.Easyforex = append(hisData.Easyforex, candleStrings)
  739. //easyforexMap[candles[cindex].Timestamp] = candles[cindex]
  740. easyforexCandles = append(easyforexCandles, candles[cindex])
  741. easyforexTimestampMap[candles[cindex].Timestamp] = len(easyforexCandles) - 1
  742. //tmpTime := time.Unix(candles[cindex].Timestamp/1000, 0)
  743. //if tmpTime.Hour() != 0 || tmpTime.Minute() != 0 || tmpTime.Second() != 0 {
  744. //log.Println("data error", v, tmpTime)
  745. //}
  746. }
  747. if v == "oanda" {
  748. //hisData.Oanda = append(hisData.Oanda, candleStrings)
  749. //oandaMap[candles[cindex].Timestamp] = candles[cindex]
  750. oandaCandles = append(oandaCandles, candles[cindex])
  751. oandaTimestampMap[candles[cindex].Timestamp] = len(oandaCandles) - 1
  752. //log.Println("hhhhhhh", oandaCandles)
  753. }
  754. }
  755. }
  756. if bEnd {
  757. //log.Println("test", v)
  758. break
  759. }
  760. }
  761. if v == "main" {
  762. for endCount := 1; endCount < typeCount; endCount++ {
  763. endCh <- end
  764. }
  765. //log.Println("test", v, end)
  766. }
  767. if v == "easyforex" {
  768. index := -1 //var index int
  769. for _, iMain := range mainTimestamps {
  770. var candleStrings [6]string
  771. vEasyforex, ok := easyforexTimestampMap[iMain]
  772. if ok {
  773. candleStrings[1] = fmt.Sprintf("%f", easyforexCandles[vEasyforex].Open)
  774. candleStrings[2] = fmt.Sprintf("%f", easyforexCandles[vEasyforex].High)
  775. candleStrings[3] = fmt.Sprintf("%f", easyforexCandles[vEasyforex].Low)
  776. candleStrings[4] = fmt.Sprintf("%f", easyforexCandles[vEasyforex].Close)
  777. index = vEasyforex
  778. } else {
  779. //tmpTime := time.Unix(iMain/1000, 0)
  780. //log.Println("data mismatch", tmpTime)
  781. /*if index < (len(easyforexCandles) - 1) {
  782. candleStrings[1] = fmt.Sprintf("%f", easyforexCandles[index+1].Open)
  783. candleStrings[2] = fmt.Sprintf("%f", easyforexCandles[index+1].High)
  784. candleStrings[3] = fmt.Sprintf("%f", easyforexCandles[index+1].Low)
  785. candleStrings[4] = fmt.Sprintf("%f", easyforexCandles[index+1].Close)
  786. } else {
  787. candleStrings[1] = fmt.Sprintf("%f", 0.0)
  788. candleStrings[2] = fmt.Sprintf("%f", 0.0)
  789. candleStrings[3] = fmt.Sprintf("%f", 0.0)
  790. candleStrings[4] = fmt.Sprintf("%f", 0.0)
  791. }*/
  792. if index != -1 {
  793. candleStrings[1] = fmt.Sprintf("%f", easyforexCandles[index].Open)
  794. candleStrings[2] = fmt.Sprintf("%f", easyforexCandles[index].High)
  795. candleStrings[3] = fmt.Sprintf("%f", easyforexCandles[index].Low)
  796. candleStrings[4] = fmt.Sprintf("%f", easyforexCandles[index].Close)
  797. } else {
  798. candleStrings[1] = fmt.Sprintf("%f", 0.0)
  799. candleStrings[2] = fmt.Sprintf("%f", 0.0)
  800. candleStrings[3] = fmt.Sprintf("%f", 0.0)
  801. candleStrings[4] = fmt.Sprintf("%f", 0.0)
  802. }
  803. }
  804. candleStrings[0] = fmt.Sprintf("%d", iMain/1000)
  805. candleStrings[5] = fmt.Sprintf("%d", 0)
  806. hisData.Easyforex = append(hisData.Easyforex, candleStrings)
  807. }
  808. }
  809. if v == "oanda" {
  810. index := -1 //var index int
  811. //for _, vtmp := range oandaCandles {
  812. //log.Println("test3", vtmp)
  813. //}
  814. //log.Println("test3", len(oandaTimestampMap), len(oandaCandles))
  815. for _, iMain := range mainTimestamps {
  816. var candleStrings [6]string
  817. vOanda, ok := oandaTimestampMap[iMain]
  818. if ok {
  819. //log.Println(vOanda, iMain, oandaCandles[vOanda].Timestamp)
  820. candleStrings[1] = fmt.Sprintf("%f", oandaCandles[vOanda].Open)
  821. candleStrings[2] = fmt.Sprintf("%f", oandaCandles[vOanda].High)
  822. candleStrings[3] = fmt.Sprintf("%f", oandaCandles[vOanda].Low)
  823. candleStrings[4] = fmt.Sprintf("%f", oandaCandles[vOanda].Close)
  824. index = vOanda
  825. } else {
  826. /*if index < (len(oandaCandles) - 1) {
  827. candleStrings[1] = fmt.Sprintf("%f", oandaCandles[index+1].Open)
  828. candleStrings[2] = fmt.Sprintf("%f", oandaCandles[index+1].High)
  829. candleStrings[3] = fmt.Sprintf("%f", oandaCandles[index+1].Low)
  830. candleStrings[4] = fmt.Sprintf("%f", oandaCandles[index+1].Close)
  831. } else {
  832. candleStrings[1] = fmt.Sprintf("%f", 0.0)
  833. candleStrings[2] = fmt.Sprintf("%f", 0.0)
  834. candleStrings[3] = fmt.Sprintf("%f", 0.0)
  835. candleStrings[4] = fmt.Sprintf("%f", 0.0)
  836. }*/
  837. if index != -1 {
  838. candleStrings[1] = fmt.Sprintf("%f", oandaCandles[index].Open)
  839. candleStrings[2] = fmt.Sprintf("%f", oandaCandles[index].High)
  840. candleStrings[3] = fmt.Sprintf("%f", oandaCandles[index].Low)
  841. candleStrings[4] = fmt.Sprintf("%f", oandaCandles[index].Close)
  842. } else {
  843. candleStrings[1] = fmt.Sprintf("%f", 0.0)
  844. candleStrings[2] = fmt.Sprintf("%f", 0.0)
  845. candleStrings[3] = fmt.Sprintf("%f", 0.0)
  846. candleStrings[4] = fmt.Sprintf("%f", 0.0)
  847. }
  848. }
  849. candleStrings[0] = fmt.Sprintf("%d", iMain/1000)
  850. candleStrings[5] = fmt.Sprintf("%d", 0)
  851. hisData.Oanda = append(hisData.Oanda, candleStrings)
  852. }
  853. }
  854. done <- true
  855. }()
  856. }
  857. for i := 0; i < typeCount; i++ {
  858. <-done
  859. }
  860. output := getDownOutput(cb, &hisData)
  861. io.WriteString(w, output)
  862. }
  863. func symbolsHandler(w http.ResponseWriter, r *http.Request) {
  864. cb := r.FormValue("callback")
  865. //log.Println(cb)
  866. var symbols []SymbolData
  867. /*for i := markinfo.EURUSD; i < markinfo.CurrencyCount; i++ {
  868. var symbol SymbolData
  869. symbol.Symbol = i
  870. symbol.Name, _ = markinfo.SymbolName(i)
  871. symbol.PriceIncrement, _ = markinfo.SymbolUint(symbol.Name)
  872. symbol.Unit = int64(1 / symbol.PriceIncrement)
  873. if (symbol.Unit % 10) == 9 {
  874. symbol.Unit++
  875. }
  876. symbols = append(symbols, symbol)
  877. }*/
  878. symbol1 := SymbolData{Unit: 500, PriceIncrement: 0.001, Symbol: 20, Name: "XAGUSD"}
  879. symbols = append(symbols, symbol1)
  880. symbol2 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 38, Name: "EURMXN"}
  881. symbols = append(symbols, symbol2)
  882. symbol3 := SymbolData{Unit: 100, PriceIncrement: 0.01, Symbol: 22, Name: "OILUSD"}
  883. symbols = append(symbols, symbol3)
  884. symbol4 := SymbolData{Unit: 10000, PriceIncrement: 0.0001, Symbol: 26, Name: "EURCZK"}
  885. symbols = append(symbols, symbol4)
  886. symbol5 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 39, Name: "GBPMXN"}
  887. symbols = append(symbols, symbol5)
  888. symbol6 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 62, Name: "NZDCAD"}
  889. symbols = append(symbols, symbol6)
  890. symbol7 := SymbolData{Unit: 10, PriceIncrement: 0.01, Symbol: 21, Name: "XAUUSD"}
  891. symbols = append(symbols, symbol7)
  892. symbol8 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 56, Name: "EURZAR"}
  893. symbols = append(symbols, symbol8)
  894. symbol9 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 52, Name: "GBPSGD"}
  895. symbols = append(symbols, symbol9)
  896. symbol10 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 25, Name: "GBPCAD"}
  897. symbols = append(symbols, symbol10)
  898. symbol11 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 58, Name: "USDZAR"}
  899. symbols = append(symbols, symbol11)
  900. symbol12 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 50, Name: "USDSEK"}
  901. symbols = append(symbols, symbol12)
  902. symbol13 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 23, Name: "USDTRY"}
  903. symbols = append(symbols, symbol13)
  904. symbol14 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 6, Name: "NZDUSD"}
  905. symbols = append(symbols, symbol14)
  906. symbol15 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 18, Name: "USDMXN"}
  907. symbols = append(symbols, symbol15)
  908. symbol16 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 42, Name: "USDNOK"}
  909. symbols = append(symbols, symbol16)
  910. symbol17 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 32, Name: "EURHKD"}
  911. symbols = append(symbols, symbol17)
  912. symbol18 := SymbolData{Unit: 10000, PriceIncrement: 0.001, Symbol: 35, Name: "EURHUF"}
  913. symbols = append(symbols, symbol18)
  914. symbol19 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 55, Name: "GBPTRY"}
  915. symbols = append(symbols, symbol19)
  916. symbol20 := SymbolData{Unit: 10000, PriceIncrement: 0.0001, Symbol: 28, Name: "USDCZK"}
  917. symbols = append(symbols, symbol20)
  918. symbol21 := SymbolData{Unit: 10000, PriceIncrement: 0.001, Symbol: 37, Name: "USDHUF"}
  919. symbols = append(symbols, symbol21)
  920. symbol22 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 4, Name: "AUDUSD"}
  921. symbols = append(symbols, symbol22)
  922. symbol23 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 5, Name: "USDCAD"}
  923. symbols = append(symbols, symbol23)
  924. symbol24 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 60, Name: "AUDCHF"}
  925. symbols = append(symbols, symbol24)
  926. symbol25 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 29, Name: "EURDKK"}
  927. symbols = append(symbols, symbol25)
  928. symbol26 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 47, Name: "USDPLN"}
  929. symbols = append(symbols, symbol26)
  930. symbol27 := SymbolData{Unit: 10000, PriceIncrement: 0.0001, Symbol: 27, Name: "GBPCZK"}
  931. symbols = append(symbols, symbol27)
  932. symbol28 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 41, Name: "GBPNOK"}
  933. symbols = append(symbols, symbol28)
  934. symbol29 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 1, Name: "GBPUSD"}
  935. symbols = append(symbols, symbol29)
  936. symbol30 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 3, Name: "USDCHF"}
  937. symbols = append(symbols, symbol30)
  938. symbol31 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 51, Name: "EURSGD"}
  939. symbols = append(symbols, symbol31)
  940. symbol32 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 24, Name: "GBPAUD"}
  941. symbols = append(symbols, symbol32)
  942. symbol33 := SymbolData{Unit: 10000, PriceIncrement: 0.001, Symbol: 14, Name: "CHFJPY"}
  943. symbols = append(symbols, symbol33)
  944. symbol34 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 30, Name: "GBPDKK"}
  945. symbols = append(symbols, symbol34)
  946. symbol35 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 57, Name: "GBPZAR"}
  947. symbols = append(symbols, symbol35)
  948. symbol36 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 63, Name: "NZDCHF"}
  949. symbols = append(symbols, symbol36)
  950. symbol37 := SymbolData{Unit: 1, PriceIncrement: 0.1, Symbol: 68, Name: "UK100"}
  951. symbols = append(symbols, symbol37)
  952. symbol38 := SymbolData{Unit: 25, PriceIncrement: 0.1, Symbol: 70, Name: "SPX"}
  953. symbols = append(symbols, symbol38)
  954. symbol39 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 0, Name: "EURUSD"}
  955. symbols = append(symbols, symbol39)
  956. symbol40 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 12, Name: "GBPCHF"}
  957. symbols = append(symbols, symbol40)
  958. symbol41 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 46, Name: "GBPPLN"}
  959. symbols = append(symbols, symbol41)
  960. symbol42 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 7, Name: "EURGBP"}
  961. symbols = append(symbols, symbol42)
  962. symbol43 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 17, Name: "AUDCAD"}
  963. symbols = append(symbols, symbol43)
  964. symbol44 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 44, Name: "GBPNZD"}
  965. symbols = append(symbols, symbol44)
  966. symbol45 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 64, Name: "NZDSGD"}
  967. symbols = append(symbols, symbol45)
  968. symbol46 := SymbolData{Unit: 10000, PriceIncrement: 0.001, Symbol: 16, Name: "AUDJPY"}
  969. symbols = append(symbols, symbol46)
  970. symbol47 := SymbolData{Unit: 1, PriceIncrement: 0.1, Symbol: 74, Name: "STOXX50E"}
  971. symbols = append(symbols, symbol47)
  972. symbol48 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 53, Name: "USDSGD"}
  973. symbols = append(symbols, symbol48)
  974. symbol49 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 9, Name: "EURCHF"}
  975. symbols = append(symbols, symbol49)
  976. symbol50 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 40, Name: "EURNOK"}
  977. symbols = append(symbols, symbol50)
  978. symbol51 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 43, Name: "EURNZD"}
  979. symbols = append(symbols, symbol51)
  980. symbol52 := SymbolData{Unit: 10000, PriceIncrement: 0.001, Symbol: 59, Name: "NZDJPY"}
  981. symbols = append(symbols, symbol52)
  982. symbol53 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 34, Name: "USDHKD"}
  983. symbols = append(symbols, symbol53)
  984. symbol54 := SymbolData{Unit: 10000, PriceIncrement: 0.001, Symbol: 2, Name: "USDJPY"}
  985. symbols = append(symbols, symbol54)
  986. symbol55 := SymbolData{Unit: 10000, PriceIncrement: 0.001, Symbol: 15, Name: "CADJPY"}
  987. symbols = append(symbols, symbol55)
  988. symbol56 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 45, Name: "EURPLN"}
  989. symbols = append(symbols, symbol56)
  990. symbol57 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 33, Name: "GBPHKD"}
  991. symbols = append(symbols, symbol57)
  992. symbol58 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 48, Name: "EURSEK"}
  993. symbols = append(symbols, symbol58)
  994. symbol59 := SymbolData{Unit: 1, PriceIncrement: 0.1, Symbol: 73, Name: "FCHI"}
  995. symbols = append(symbols, symbol59)
  996. symbol60 := SymbolData{Unit: 10, PriceIncrement: 0.1, Symbol: 71, Name: "NDX"}
  997. symbols = append(symbols, symbol60)
  998. symbol61 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 10, Name: "EURAUD"}
  999. symbols = append(symbols, symbol61)
  1000. symbol62 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 19, Name: "AUDNZD"}
  1001. symbols = append(symbols, symbol62)
  1002. symbol63 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 54, Name: "EURTRY"}
  1003. symbols = append(symbols, symbol63)
  1004. symbol64 := SymbolData{Unit: 10000, PriceIncrement: 0.001, Symbol: 36, Name: "GBPHUF"}
  1005. symbols = append(symbols, symbol64)
  1006. symbol65 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 49, Name: "GBPSEK"}
  1007. symbols = append(symbols, symbol65)
  1008. symbol66 := SymbolData{Unit: 2.5, PriceIncrement: 0.1, Symbol: 72, Name: "GDAXI"}
  1009. symbols = append(symbols, symbol66)
  1010. symbol67 := SymbolData{Unit: 10000, PriceIncrement: 0.001, Symbol: 8, Name: "EURJPY"}
  1011. symbols = append(symbols, symbol67)
  1012. symbol68 := SymbolData{Unit: 10000, PriceIncrement: 0.001, Symbol: 13, Name: "GBPJPY"}
  1013. symbols = append(symbols, symbol68)
  1014. symbol69 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 11, Name: "EURCAD"}
  1015. symbols = append(symbols, symbol69)
  1016. symbol70 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 61, Name: "CADCHF"}
  1017. symbols = append(symbols, symbol70)
  1018. symbol71 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 31, Name: "USDDKK"}
  1019. symbols = append(symbols, symbol71)
  1020. symbol72 := SymbolData{Unit: 1, PriceIncrement: 1, Symbol: 69, Name: "WS30"}
  1021. symbols = append(symbols, symbol72)
  1022. symbol73 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 65, Name: "LTCUSD"}
  1023. symbols = append(symbols, symbol73)
  1024. symbol74 := SymbolData{Unit: 10000, PriceIncrement: 0.001, Symbol: 66, Name: "BTCUSD"}
  1025. symbols = append(symbols, symbol74)
  1026. b, _ := json.Marshal(symbols)
  1027. output := fmt.Sprintf("if (%s) %s(%s)\n", cb, cb, string(b))
  1028. io.WriteString(w, output)
  1029. }
  1030. /*
  1031. func testHandler(w http.ResponseWriter, r *http.Request) {
  1032. insId := r.FormValue("insid")
  1033. period := r.FormValue("period")
  1034. st := r.FormValue("st")
  1035. et := r.FormValue("et")
  1036. log.Println(insId, period, st, et)
  1037. periodId, ok := market.PeriodIdMap[period]
  1038. if !ok {
  1039. http.Error(w, "webserver doesn't support period", http.StatusBadRequest)
  1040. return
  1041. }
  1042. st64, _ := strconv.ParseInt(st, 10, 64)
  1043. et64, _ := strconv.ParseInt(et, 10, 64)
  1044. fnames, err := clientDown.GetHisEx(insId, periodId, st64, et64, false)
  1045. if err != nil {
  1046. http.Error(w, "webserver can't get data", http.StatusBadRequest)
  1047. return
  1048. }
  1049. sort.Sort(byDlInfo(fnames))
  1050. var output string
  1051. for i, v := range fnames {
  1052. output += fmt.Sprintf("%d %s %s %d %d %d", i, v.Fname, v.Reply.Url, v.Reply.St, v.Reply.Et, v.Reply.N)
  1053. }
  1054. io.WriteString(w, output)
  1055. }
  1056. */
  1057. type gzipResponseWriter struct {
  1058. io.Writer
  1059. http.ResponseWriter
  1060. }
  1061. func (w gzipResponseWriter) Write(b []byte) (int, error) {
  1062. return w.Writer.Write(b)
  1063. }
  1064. func (w gzipResponseWriter) Flush() {
  1065. w.Writer.(*gzip.Writer).Flush()
  1066. w.ResponseWriter.(http.Flusher).Flush()
  1067. }
  1068. func makeGzipHandler(fn http.HandlerFunc) http.HandlerFunc {
  1069. return func(w http.ResponseWriter, r *http.Request) {
  1070. if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
  1071. fn(w, r)
  1072. return
  1073. }
  1074. w.Header().Set("Content-Encoding", "gzip")
  1075. w.Header().Set("Content-Type", "text/javascript")
  1076. gz := gzip.NewWriter(w)
  1077. defer gz.Close()
  1078. fn(gzipResponseWriter{Writer: gz, ResponseWriter: w}, r)
  1079. }
  1080. }
  1081. func main() {
  1082. runtime.GOMAXPROCS(runtime.NumCPU())
  1083. conf, err := readConf()
  1084. if err != nil {
  1085. flag.Parse()
  1086. } else {
  1087. *saddr1 = conf.Saddr1
  1088. *saddr2 = conf.Saddr2
  1089. *saddr3 = conf.Saddr3
  1090. *saddr4 = conf.Saddr4
  1091. }
  1092. err = connectServer()
  1093. if err != nil {
  1094. log.Fatal("connect server", err)
  1095. }
  1096. //go updateTick()
  1097. s := &http.Server{
  1098. Addr: ":6062",
  1099. ReadTimeout: 10 * time.Second,
  1100. WriteTimeout: 10 * time.Second,
  1101. MaxHeaderBytes: 1 << 20,
  1102. }
  1103. //http.HandleFunc("/tickdata", tickHandler)
  1104. //http.HandleFunc("/api.php", makeGzipHandler(downHandler))
  1105. //http.HandleFunc("/symbols", symbolsHandler)
  1106. http.HandleFunc("/daydata", dayHandler)
  1107. http.HandleFunc("/h24data", h24Handler)
  1108. //http.HandleFunc("/test", testHandler)
  1109. log.Fatal(s.ListenAndServe())
  1110. }