main.go 43 KB

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