// main.go package main import ( "compress/gzip" "encoding/json" "errors" "flag" "fmt" "io" "log" "net/http" "os" "runtime" "strconv" "strings" "sync" "time" "tickserver/client" "tickserver/framework/base" "tickserver/markinfo" "tickserver/server/market" ) type RealTick struct { tg base.TickGo //tgCh <-chan base.TickGo now int64 } type Options struct { Start int `json:"start"` End int `json:"end"` Total int `json:"total_size"` } type KCandle struct { X []int `json:"x"` Y [][5]float32 `json:"y"` } type KVolume struct { X []int `json:"x"` Y []int `json:"y"` } type KData struct { C string `json:"c"` P string `json:"p"` Action string `json:"action"` KOptions Options `json:"options"` Candles KCandle `json:"main"` Volumes KVolume `json:"volumes|||__ignore__"` } type HistoryData struct { C string `json:"c"` P string `json:"p"` Action string `json:"action"` End int64 `json:"end"` MainData [][6]string `json:"main"` Easyforex [][6]string `json:"easyforex"` Oanda [][6]string `json:"oanda"` } type SymbolData struct { Unit float64 PriceIncrement float64 Symbol int Name string } //type byDlInfo []market.DlInfo //func (a byDlInfo) Len() int { return len(a) } //func (a byDlInfo) Swap(i, j int) { a[i], a[j] = a[j], a[i] } //func (a byDlInfo) Less(i, j int) bool { return a[i].Reply.St < a[j].Reply.St } var saddr1 = flag.String("s1", "127.0.0.1:19528", "tick server address 1") //115.231.103.7 var saddr2 = flag.String("s2", "127.0.0.1:19528", "tick server address 2") //127.0.0.1 var saddr3 = flag.String("s3", "127.0.0.1:19529", "tick server address 3") //115.236.75.194 var saddr4 = flag.String("s4", "127.0.0.1:9090", "tick server address 4") //19528 9090 var clientSub *client.ClientSimple var clientDown *client.ClientSimple var tkMap = make(map[string]base.TickGo) var tkMutex sync.Mutex type Conf struct { Saddr1 string // Saddr2 string // Saddr3 string // Saddr4 string } type SpecialTick struct { Timestamp int64 `json:"ts"` Open float64 `json:"open"` High float64 `json:"high"` Low float64 `json:"low"` Last float64 `json:"last"` Volume float64 `json:"volume"` } type StringSpecialTick struct { Timestamp string `json:"ts"` Open string `json:"open"` High string `json:"high"` Low string `json:"low"` Last string `json:"last"` Volume string `json:"volume"` } func readConf() (*Conf, error) { f, err := os.Open("webproxy.json") if err != nil { return nil, err } defer f.Close() dec := json.NewDecoder(f) conf := &Conf{} err = dec.Decode(conf) if err != nil { return nil, err } return conf, nil } func getStringSTK(stk SpecialTick, insId string) StringSpecialTick { sstk := StringSpecialTick{ Timestamp: fmt.Sprintf("%d", stk.Timestamp), Open: fmt.Sprintf("%.4f", stk.Open), } switch insId { case "bty_BCCBTC": sstk.Last = fmt.Sprintf("%.4f", stk.Last) sstk.High = fmt.Sprintf("%.4f", stk.High) sstk.Low = fmt.Sprintf("%.4f", stk.Low) sstk.Volume = fmt.Sprintf("%.4f", stk.Volume) case "bty_ETHBTC": sstk.Last = fmt.Sprintf("%.5f", stk.Last) sstk.High = fmt.Sprintf("%.5f", stk.High) sstk.Low = fmt.Sprintf("%.5f", stk.Low) sstk.Volume = fmt.Sprintf("%.3f", stk.Volume) case "bty_ETCBTC": sstk.Last = fmt.Sprintf("%.6f", stk.Last) sstk.High = fmt.Sprintf("%.6f", stk.High) sstk.Low = fmt.Sprintf("%.6f", stk.Low) sstk.Volume = fmt.Sprintf("%.2f", stk.Volume) case "bty_ZECBTC": sstk.Last = fmt.Sprintf("%.5f", stk.Last) sstk.High = fmt.Sprintf("%.5f", stk.High) sstk.Low = fmt.Sprintf("%.5f", stk.Low) sstk.Volume = fmt.Sprintf("%.3f", stk.Volume) case "bty_LTCBTC": sstk.Last = fmt.Sprintf("%.6f", stk.Last) sstk.High = fmt.Sprintf("%.6f", stk.High) sstk.Low = fmt.Sprintf("%.6f", stk.Low) sstk.Volume = fmt.Sprintf("%.2f", stk.Volume) case "bty_BTCUSDT": sstk.Last = fmt.Sprintf("%.2f", stk.Last) sstk.High = fmt.Sprintf("%.2f", stk.High) sstk.Low = fmt.Sprintf("%.2f", stk.Low) sstk.Volume = fmt.Sprintf("%.4f", stk.Volume) case "bty_BCCUSDT": sstk.Last = fmt.Sprintf("%.2f", stk.Last) sstk.High = fmt.Sprintf("%.2f", stk.High) sstk.Low = fmt.Sprintf("%.2f", stk.Low) sstk.Volume = fmt.Sprintf("%.4f", stk.Volume) case "bty_ETHUSDT": sstk.Last = fmt.Sprintf("%.2f", stk.Last) sstk.High = fmt.Sprintf("%.2f", stk.High) sstk.Low = fmt.Sprintf("%.2f", stk.Low) sstk.Volume = fmt.Sprintf("%.3f", stk.Volume) case "bty_ETCUSDT": sstk.Last = fmt.Sprintf("%.2f", stk.Last) sstk.High = fmt.Sprintf("%.2f", stk.High) sstk.Low = fmt.Sprintf("%.2f", stk.Low) sstk.Volume = fmt.Sprintf("%.2f", stk.Volume) case "bty_ZECUSDT": sstk.Last = fmt.Sprintf("%.2f", stk.Last) sstk.High = fmt.Sprintf("%.2f", stk.High) sstk.Low = fmt.Sprintf("%.2f", stk.Low) sstk.Volume = fmt.Sprintf("%.3f", stk.Volume) case "bty_LTCUSDT": sstk.Last = fmt.Sprintf("%.2f", stk.Last) sstk.High = fmt.Sprintf("%.2f", stk.High) sstk.Low = fmt.Sprintf("%.2f", stk.Low) sstk.Volume = fmt.Sprintf("%.2f", stk.Volume) case "bty_YCCUSDT": fallthrough case "bty_BTYUSDT": sstk.Last = fmt.Sprintf("%.4f", stk.Last) sstk.High = fmt.Sprintf("%.4f", stk.High) sstk.Low = fmt.Sprintf("%.4f", stk.Low) sstk.Volume = fmt.Sprintf("%.1f", stk.Volume) case "bty_BTCSUSDT": sstk.Last = fmt.Sprintf("%.2f", stk.Last) sstk.High = fmt.Sprintf("%.2f", stk.High) sstk.Low = fmt.Sprintf("%.2f", stk.Low) sstk.Volume = fmt.Sprintf("%.2f", stk.Volume) case "bty_SCUSDT": sstk.Last = fmt.Sprintf("%.6f", stk.Last) sstk.High = fmt.Sprintf("%.6f", stk.High) sstk.Low = fmt.Sprintf("%.6f", stk.Low) sstk.Volume = fmt.Sprintf("%.0f", stk.Volume) case "bty_BTSUSDT": sstk.Last = fmt.Sprintf("%.4f", stk.Last) sstk.High = fmt.Sprintf("%.4f", stk.High) sstk.Low = fmt.Sprintf("%.4f", stk.Low) sstk.Volume = fmt.Sprintf("%.2f", stk.Volume) case "bty_DCRUSDT": sstk.Last = fmt.Sprintf("%.2f", stk.Last) sstk.High = fmt.Sprintf("%.2f", stk.High) sstk.Low = fmt.Sprintf("%.2f", stk.Low) sstk.Volume = fmt.Sprintf("%.2f", stk.Volume) default: } return sstk } func dayHandler(w http.ResponseWriter, r *http.Request) { //cb := r.FormValue("callback") typ := r.FormValue("type") symbol := r.FormValue("symbol") //log.Println(cb, typ, symbol) insId := typ + "_" + symbol candles, err := clientDown.GetLastCandles(insId, market.D1, 1) if err != nil { http.Error(w, "server get data failed", http.StatusInternalServerError) return } if len(candles) == 0 { _, candles, _ = clientDown.GetHistory(insId, market.D1, -1, -1) } if len(candles) == 0 { http.Error(w, "server get data failed", http.StatusInternalServerError) return } stk := SpecialTick{Timestamp: candles[0].Timestamp / 1000, Open: candles[0].Open, High: candles[0].High, Low: candles[0].Low, Last: candles[0].Close, Volume: candles[0].RealVolums} sstk := getStringSTK(stk, insId) b, err := json.Marshal(&sstk) if err != nil { http.Error(w, "json encoding error", http.StatusInternalServerError) return } w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Add("Access-Control-Allow-Headers", "Content-Type") w.Header().Set("content-type", "application/json") io.WriteString(w, string(b)) } func h24Handler(w http.ResponseWriter, r *http.Request) { //cb := r.FormValue("callback") typ := r.FormValue("type") symbol := r.FormValue("symbol") //log.Println(cb, typ, symbol) var candles []client.Candle insId := typ + "_" + symbol bufcandles, err := clientDown.GetLastCandles(insId, market.H1, 24) /*for i, _ := range bufcandles { if insId == "bty_ETHUSDT" { if bufcandles[i].Timestamp >= 1524031200000 && bufcandles[i].Timestamp <= 1524031200000 { bufcandles[i].High = bufcandles[i-1].High bufcandles[i].Open = bufcandles[i-1].Open bufcandles[i].Close = bufcandles[i-1].Close bufcandles[i].Low = bufcandles[i-1].Low } } if insId == "bty_BTCUSDT" { if bufcandles[i].Timestamp >= 1524034800000 && bufcandles[i].Timestamp <= 1524034800000 { bufcandles[i].High = bufcandles[i-1].High bufcandles[i].Open = bufcandles[i-1].Open bufcandles[i].Close = bufcandles[i-1].Close bufcandles[i].Low = bufcandles[i-1].Low } } if insId == "bty_BCCUSDT" { if bufcandles[i].Timestamp >= 1524031200000 && bufcandles[i].Timestamp <= 1524034800000 { bufcandles[i].High = bufcandles[i-1].High bufcandles[i].Open = bufcandles[i-1].Open bufcandles[i].Close = bufcandles[i-1].Close bufcandles[i].Low = bufcandles[i-1].Low } } if insId == "bty_ETCUSDT" { if bufcandles[i].Timestamp >= 1524031200000 && bufcandles[i].Timestamp <= 1524034800000 { bufcandles[i].High = bufcandles[i-1].High bufcandles[i].Open = bufcandles[i-1].Open bufcandles[i].Close = bufcandles[i-1].Close bufcandles[i].Low = bufcandles[i-1].Low } } if insId == "bty_ZECUSDT" { if bufcandles[i].Timestamp >= 1524031200000 && bufcandles[i].Timestamp <= 1524034800000 { bufcandles[i].High = bufcandles[i-1].High bufcandles[i].Open = bufcandles[i-1].Open bufcandles[i].Close = bufcandles[i-1].Close bufcandles[i].Low = bufcandles[i-1].Low } } if insId == "bty_LTCUSDT" { if bufcandles[i].Timestamp >= 1524031200000 && bufcandles[i].Timestamp <= 1524034800000 { bufcandles[i].High = bufcandles[i-1].High bufcandles[i].Open = bufcandles[i-1].Open bufcandles[i].Close = bufcandles[i-1].Close bufcandles[i].Low = bufcandles[i-1].Low } } if insId == "bty_DCRUSDT" { if bufcandles[i].Timestamp >= 1524031200000 && bufcandles[i].Timestamp <= 1524034800000 { bufcandles[i].High = bufcandles[i-1].High bufcandles[i].Open = bufcandles[i-1].Open bufcandles[i].Close = bufcandles[i-1].Close bufcandles[i].Low = bufcandles[i-1].Low } } }*/ if err != nil { http.Error(w, "server get data failed", http.StatusInternalServerError) return } else { //fmt.Println("h24 1", len(bufcandles), bufcandles[0], bufcandles[len(bufcandles)-1]) if len(bufcandles) < 24 { _, filecandles, _ := clientDown.GetHistory(insId, market.H1, -24, -1) //fmt.Println("h24 2", len(filecandles), filecandles[0], filecandles[len(filecandles)-1]) var candlesDesc []client.Candle var bufCandleTime int64 if len(bufcandles) > 0 { bufCandleTime = bufcandles[0].Timestamp } for i := 0; i < len(filecandles); i++ { if filecandles[i].Timestamp < bufCandleTime { candlesDesc = append(candlesDesc, filecandles[i]) } if len(candlesDesc) >= (24 - len(bufcandles)) { break } } for i := len(candlesDesc) - 1; i >= 0; i-- { candles = append(candles, candlesDesc[i]) } //fmt.Println("h24 3", len(candles), candles[0], candles[len(candles)-1]) candles = append(candles, bufcandles[:]...) //fmt.Println("h24 4", len(candles), candles[0], candles[len(candles)-1]) } else { candles = bufcandles[:] } var stk SpecialTick if len(candles) > 0 { stk.Low = candles[0].Low stk.Open = candles[0].Open stk.Timestamp = candles[0].Timestamp / 1000 for i := 0; i < len(candles); i++ { //fmt.Println("h24 5", i, candles[i]) stk.Volume += candles[i].RealVolums if candles[i].High > stk.High { stk.High = candles[i].High } if candles[i].Low < stk.Low { stk.Low = candles[i].Low } stk.Last = candles[i].Close } } sstk := getStringSTK(stk, insId) b, err := json.Marshal(&sstk) if err != nil { http.Error(w, "json encoding error", http.StatusInternalServerError) return } w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Add("Access-Control-Allow-Headers", "Content-Type") w.Header().Set("content-type", "application/json") io.WriteString(w, string(b)) } } func subTick(insId string, symbolId int16) error { ins := clientSub.GetIns(insId) if ins == nil { errinfo := fmt.Sprintf("instrument %s not supported.", insId) return errors.New(errinfo) } clientSub.SubMarket(insId) ins.OnMarket().Attach(func(v interface{}) error { m, ok := v.(*client.Market) if !ok { //log.Println("v.(*Market) is NOT ok", insId) err := errors.New("v.(*Market) is NOT ok") return err } if m.InsId != insId { //log.Println("m.InsId != insId", m.InsId, insId) err := errors.New("v.(*Market) insid is NOT ok") return err } //log.Println("@@@:Market:", m) //now := time.Now() //timestampNow := now.Unix()*1000 + int64(now.Nanosecond())/1000000 //log.Println("query", timestampNow, m.Timestamp, timestampNow-m.Timestamp) var tg base.TickGo tg.Time = int32(m.Timestamp / 1000) tg.Ms = int16(m.Timestamp % 1000) tg.Symbol = symbolId tg.Ask = float32(m.LastPrice) tg.Bid = float32(m.LastPrice) tg.Askv = float32(m.Volume) tg.Bidv = float32(m.Volume) if tg.Ask != 0. && tg.Bid != 0. { tkMutex.Lock() tkMap[insId] = tg tkMutex.Unlock() } else { //log.Println("value of ask or bid is 0", tg) } //log.Println(tg) return nil }) return nil } func getOutput(cb string, ticks []base.TickGo) (output string) { b, err := json.Marshal(ticks) if err != nil { //log.Println(err) } output = fmt.Sprintf("if (%s) %s(%s)\n", cb, cb, string(b)) return output } func connectServer() (err error) { clientSub, err = client.NewClientSimple(*saddr1, *saddr2, *saddr3, *saddr4, "./tmp") if err != nil { //log.Println("new client", err) return err } //insMap := clientSub.GetInsMap() //for insId, ins := range insMap { //log.Println(insId, ins) //} clientDown, err = client.NewClientSimple(*saddr1, *saddr2, *saddr3, *saddr4, "./tmp") if err != nil { //log.Println("new client", err) return err } return nil } func tickHandler(w http.ResponseWriter, r *http.Request) { //log.Println(r) //_, ok := w.(http.Hijacker) //if !ok { //http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError) //return //} else { //} cb := r.FormValue("callback") typ := r.FormValue("type") symbol := r.FormValue("symbol") //log.Println(cb, typ, symbol) symbols := make([]string, 0) if symbol == "" { insMap := clientSub.GetInsMap() for _, v := range insMap { insTyp := strings.Split(v.Id, "_")[0] insSymbol := strings.Split(v.Id, "_")[1] if insTyp == typ { if typ == "lmax" { bookId, err := strconv.Atoi(insSymbol) if err != nil { continue } symbolId, err := markinfo.BookIdToSymbolId(bookId) if err != nil { continue } insSymbol, err = markinfo.SymbolName(symbolId) if err != nil { continue } } symbols = append(symbols, insSymbol) } } } else { symbols = strings.Split(symbol, ",") } ticks := make([]base.TickGo, 0) for _, v := range symbols { symbolId, err := markinfo.SymbolId(v) if err != nil { if typ == "lmax" && v == "CRUDE" { symbolId = markinfo.OILUSD } // else { //http.Error(w, "webserver doesn't support symbol", http.StatusBadRequest) //return //} } myInsId := typ + "_" + v if typ == "lmax" { lmaxId, err := markinfo.SymbolIdToBookId(symbolId) if err != nil { if typ == "lmax" && (v == "CRUDE" || v == "OILUSD") { lmaxId = 100800 } else { http.Error(w, "webserver doesn't support symbol", http.StatusBadRequest) return } } slmaxId := fmt.Sprintf("%d", lmaxId) myInsId = typ + "_" + slmaxId } tkMutex.Lock() tick, ok := tkMap[myInsId] tkMutex.Unlock() if ok { /*if typ == "lmax" { tick.Time = int32(time.Now().Unix()) tick.Ms = 0 }*/ ticks = append(ticks, tick) } else { /*if typ == "lmax" { tmpticks, err := clientSub.GetTickHistory(myInsId, -1, -1) if len(tmpticks) > 0 { tick.Time = int32(time.Now().Unix()) //int32(tmpticks[0].Timestamp / 1000) tick.Ms = 0 //int16(tmpticks[0].Timestamp % 1000) tick.Symbol = int16(symbolId) tick.Ask = float32(tmpticks[0].Price) tick.Bid = float32(tmpticks[0].Price) tick.Askv = int32(tmpticks[0].Volume) tick.Bidv = int32(tmpticks[0].Volume) ticks = append(ticks, tick) tkMutex.Lock() tkMap[myInsId] = tick tkMutex.Unlock() } log.Println("fuck", err, len(tmpticks)) }*/ err := subTick(myInsId, int16(symbolId)) if err != nil { //log.Println(err) } } } output := getOutput(cb, ticks) io.WriteString(w, output) } func getDownOutput(cb string, hisData *HistoryData) (output string) { b, err := json.Marshal(hisData) if err != nil { //log.Println(err) } if len(cb) > 0 { output = fmt.Sprintf("if (%s) %s(%s)\n", cb, cb, string(b)) } else { output = string(b) + "\n" } return output } func candle2Str(candle market.Candle) [6]string { var candleStrings [6]string candleStrings[0] = fmt.Sprintf("%d", candle.Timestamp/1000) candleStrings[1] = fmt.Sprintf("%f", candle.Open) candleStrings[2] = fmt.Sprintf("%f", candle.High) candleStrings[3] = fmt.Sprintf("%f", candle.Low) candleStrings[4] = fmt.Sprintf("%f", candle.Close) candleStrings[5] = fmt.Sprintf("%d", 0) return candleStrings } func downHandler(w http.ResponseWriter, r *http.Request) { symbol := r.FormValue("c") period := r.FormValue("p") action := r.FormValue("action") count := r.FormValue("count") typ := r.FormValue("type") //out := r.FormValue("out") cb := r.FormValue("callback") var ts, te string if action == "new" { te = r.FormValue("te") } if action == "down" { ts = r.FormValue("ts") } //log.Println(symbol, period, action, count, typ, out, te, ts) symbolId, err := markinfo.SymbolId(symbol) if err != nil { if symbol == "CRUDE" { symbolId = markinfo.OILUSD } else { http.Error(w, "webserver doesn't support symbol", http.StatusBadRequest) return } } periodId, ok := market.PeriodIdMap[period] if !ok { http.Error(w, "webserver doesn't support period", http.StatusBadRequest) return } iCount, err := strconv.Atoi(count) if action != "new" && err != nil { http.Error(w, "webserver doesn't support count", http.StatusBadRequest) return } types := strings.Split(typ, "|") for i, v := range types { if v == "main" { types[i] = types[0] types[0] = v break } } typeCount := len(types) done := make(chan bool, typeCount) endCh := make(chan int64, typeCount-1) var hisData HistoryData hisData.C = symbol hisData.P = period hisData.Action = action var mainTimestamps []int64 var easyforexCandles, oandaCandles []client.Candle easyforexTimestampMap := make(map[int64]int) oandaTimestampMap := make(map[int64]int) //log.Println("test", types) for i := 0; i < typeCount; i++ { v := types[i] //for i, v := range types { var prefix string switch v { case "main": prefix = market.LmaxPrefix if symbol == "BTCCNY" || symbol == "BTCUSD" || symbol == "BTCFUSD" { prefix = market.BtcPrefix } else if symbol == "BTCETH" { prefix = market.PoloPrefix } else if symbol == "ETHCNY" || symbol == "BTYCNY" || symbol == "ETCCNY" { prefix = market.BtyPrefix } case "easyforex": prefix = market.EasyForexPrefix if symbol == "CRUDE" { symbol = "OILUSD" } case "oanda": prefix = market.OandaPrefix if symbol == "CRUDE" { symbol = "OILUSD" } } myInsId := prefix + symbol if prefix == market.LmaxPrefix { lmaxId, err := markinfo.SymbolIdToBookId(symbolId) if err != nil { if symbolId == markinfo.OILUSD { lmaxId = 100800 } else { http.Error(w, "webserver doesn't support symbol", http.StatusBadRequest) return } } slmaxId := fmt.Sprintf("%d", lmaxId) myInsId = market.LmaxPrefix + slmaxId } go func() { var end, iTE, iTS int64 var bufferedCandlesDesc []client.Candle var downN int var downTS int64 switch action { case "init": bufferedCandlesAsc, _ := clientDown.GetLastCandles(myInsId, periodId, 0x7fffffff) for cindex := len(bufferedCandlesAsc) - 1; cindex >= 0; cindex-- { bufferedCandlesDesc = append(bufferedCandlesDesc, bufferedCandlesAsc[cindex]) if len(bufferedCandlesDesc) >= iCount { break } } downN = -(iCount - len(bufferedCandlesDesc)) downTS = -1 case "new": iCount = 1000 iTE, _ = strconv.ParseInt(te, 10, 64) iTE *= 1000 bufferedCandlesAsc, _ := clientDown.GetLastCandles(myInsId, periodId, 0x7fffffff) //log.Println("haha.....", myInsId, bufferedCandlesAsc) for cindex := len(bufferedCandlesAsc) - 1; cindex >= 0; cindex-- { if bufferedCandlesAsc[cindex].Timestamp >= iTE { bufferedCandlesDesc = append(bufferedCandlesDesc, bufferedCandlesAsc[cindex]) if len(bufferedCandlesDesc) >= iCount { break } } } if len(bufferedCandlesDesc) > 0 { downN = -(iCount - len(bufferedCandlesDesc)) downTS = -1 } else { downN = iCount downTS = iTE } case "down": iTS, _ = strconv.ParseInt(ts, 10, 64) iTS *= 1000 tmpBufferedCandles, _ := clientDown.GetLastCandles(myInsId, periodId, 1) if len(tmpBufferedCandles) > 0 && tmpBufferedCandles[0].Timestamp <= iTS { bufferedCandlesAsc, _ := clientDown.GetLastCandles(myInsId, periodId, 0x7fffffff) for cindex := len(bufferedCandlesAsc) - 1; cindex >= 0; cindex-- { if bufferedCandlesAsc[cindex].Timestamp <= iTS { bufferedCandlesDesc = append(bufferedCandlesDesc, bufferedCandlesAsc[cindex]) if len(bufferedCandlesDesc) >= iCount { break } } } } if len(bufferedCandlesDesc) > 0 { downN = -(iCount - len(bufferedCandlesDesc)) downTS = -1 } else { downN = -iCount downTS = iTS } } //log.Println(myInsId, len(bufferedCandlesDesc)) //for _, candle := range bufferedCandlesDesc { //log.Println(candle) //} //log.Println("test", myInsId, periodId, downN, downTS, false) _, filecandles, _ := clientDown.GetHistory(myInsId, periodId, downN, downTS) //log.Println("test", myInsId, len(fileticks), len(filecandles)) if v != "main" { end = <-endCh } bEnd := false var timestampLast int64 timestampLast = 0x7fffffffffffffff for findex := 1; findex >= 0; findex-- { var candles []client.Candle if findex == 1 { //candles = append(candles, bufferedCandlesDesc...) for iBuffered := len(bufferedCandlesDesc) - 1; iBuffered >= 0; iBuffered-- { candles = append(candles, bufferedCandlesDesc[iBuffered]) } if v == "oanda" { //for _, vtmp := range candles { //log.Println("test1", vtmp) //} } //log.Println("buf", v, len(candles)) } else { if downN < 0 { for iFile := len(filecandles) - 1; iFile >= 0; iFile-- { candles = append(candles, filecandles[iFile]) } } else { candles = filecandles[:] } if v == "oanda" { //for _, vtmp := range candles { //log.Println("test2", vtmp) //} } //log.Println("file", v, len(candles), fnames[findex].Fname) } //log.Println("aaaa", v, candles) for cindex := len(candles) - 1; cindex >= 0; cindex-- { if v == "main" && periodId == market.D1 { tmpTime := time.Unix(candles[cindex].Timestamp/1000, 0) if tmpTime.Hour() != 0 || tmpTime.Minute() != 0 || tmpTime.Second() != 0 { //log.Println("data time not standard", v, tmpTime) //candles[cindex].Timestamp -= (int64(tmpTime.Hour())*3600 + int64(tmpTime.Minute())*60 + int64(tmpTime.Second())) * 1000 } } if candles[cindex].Timestamp >= timestampLast { continue } timestampLast = candles[cindex].Timestamp if action == "down" && candles[cindex].Timestamp > iTS { continue } if action == "new" && candles[cindex].Timestamp < iTE { continue } if v == "main" { var candleStrings [6]string candleStrings[0] = fmt.Sprintf("%d", candles[cindex].Timestamp/1000) candleStrings[1] = fmt.Sprintf("%f", candles[cindex].Open) candleStrings[2] = fmt.Sprintf("%f", candles[cindex].High) candleStrings[3] = fmt.Sprintf("%f", candles[cindex].Low) candleStrings[4] = fmt.Sprintf("%f", candles[cindex].Close) candleStrings[5] = fmt.Sprintf("%d", 0) hisData.MainData = append(hisData.MainData, candleStrings) end = candles[cindex].Timestamp mainTimestamps = append(mainTimestamps, end) //tmpTime := time.Unix(end/1000, 0) //if tmpTime.Hour() != 0 || tmpTime.Minute() != 0 || tmpTime.Second() != 0 { //log.Println("data error", v, tmpTime) //} if len(hisData.MainData) >= iCount { bEnd = true //log.Println("test", v, len(hisData.MainData)) break } } else { if candles[cindex].Timestamp < end { bEnd = true if v == "oanda" { //log.Println("test", v, end, candles[cindex].Timestamp, len(hisData.Oanda)) } if v == "easyforex" { //log.Println("test", v, end, candles[cindex].Timestamp, len(hisData.Easyforex)) } break } if v == "easyforex" { //hisData.Easyforex = append(hisData.Easyforex, candleStrings) //easyforexMap[candles[cindex].Timestamp] = candles[cindex] easyforexCandles = append(easyforexCandles, candles[cindex]) easyforexTimestampMap[candles[cindex].Timestamp] = len(easyforexCandles) - 1 //tmpTime := time.Unix(candles[cindex].Timestamp/1000, 0) //if tmpTime.Hour() != 0 || tmpTime.Minute() != 0 || tmpTime.Second() != 0 { //log.Println("data error", v, tmpTime) //} } if v == "oanda" { //hisData.Oanda = append(hisData.Oanda, candleStrings) //oandaMap[candles[cindex].Timestamp] = candles[cindex] oandaCandles = append(oandaCandles, candles[cindex]) oandaTimestampMap[candles[cindex].Timestamp] = len(oandaCandles) - 1 //log.Println("hhhhhhh", oandaCandles) } } } if bEnd { //log.Println("test", v) break } } if v == "main" { for endCount := 1; endCount < typeCount; endCount++ { endCh <- end } //log.Println("test", v, end) } if v == "easyforex" { index := -1 //var index int for _, iMain := range mainTimestamps { var candleStrings [6]string vEasyforex, ok := easyforexTimestampMap[iMain] if ok { candleStrings[1] = fmt.Sprintf("%f", easyforexCandles[vEasyforex].Open) candleStrings[2] = fmt.Sprintf("%f", easyforexCandles[vEasyforex].High) candleStrings[3] = fmt.Sprintf("%f", easyforexCandles[vEasyforex].Low) candleStrings[4] = fmt.Sprintf("%f", easyforexCandles[vEasyforex].Close) index = vEasyforex } else { //tmpTime := time.Unix(iMain/1000, 0) //log.Println("data mismatch", tmpTime) /*if index < (len(easyforexCandles) - 1) { candleStrings[1] = fmt.Sprintf("%f", easyforexCandles[index+1].Open) candleStrings[2] = fmt.Sprintf("%f", easyforexCandles[index+1].High) candleStrings[3] = fmt.Sprintf("%f", easyforexCandles[index+1].Low) candleStrings[4] = fmt.Sprintf("%f", easyforexCandles[index+1].Close) } else { candleStrings[1] = fmt.Sprintf("%f", 0.0) candleStrings[2] = fmt.Sprintf("%f", 0.0) candleStrings[3] = fmt.Sprintf("%f", 0.0) candleStrings[4] = fmt.Sprintf("%f", 0.0) }*/ if index != -1 { candleStrings[1] = fmt.Sprintf("%f", easyforexCandles[index].Open) candleStrings[2] = fmt.Sprintf("%f", easyforexCandles[index].High) candleStrings[3] = fmt.Sprintf("%f", easyforexCandles[index].Low) candleStrings[4] = fmt.Sprintf("%f", easyforexCandles[index].Close) } else { candleStrings[1] = fmt.Sprintf("%f", 0.0) candleStrings[2] = fmt.Sprintf("%f", 0.0) candleStrings[3] = fmt.Sprintf("%f", 0.0) candleStrings[4] = fmt.Sprintf("%f", 0.0) } } candleStrings[0] = fmt.Sprintf("%d", iMain/1000) candleStrings[5] = fmt.Sprintf("%d", 0) hisData.Easyforex = append(hisData.Easyforex, candleStrings) } } if v == "oanda" { index := -1 //var index int //for _, vtmp := range oandaCandles { //log.Println("test3", vtmp) //} //log.Println("test3", len(oandaTimestampMap), len(oandaCandles)) for _, iMain := range mainTimestamps { var candleStrings [6]string vOanda, ok := oandaTimestampMap[iMain] if ok { //log.Println(vOanda, iMain, oandaCandles[vOanda].Timestamp) candleStrings[1] = fmt.Sprintf("%f", oandaCandles[vOanda].Open) candleStrings[2] = fmt.Sprintf("%f", oandaCandles[vOanda].High) candleStrings[3] = fmt.Sprintf("%f", oandaCandles[vOanda].Low) candleStrings[4] = fmt.Sprintf("%f", oandaCandles[vOanda].Close) index = vOanda } else { /*if index < (len(oandaCandles) - 1) { candleStrings[1] = fmt.Sprintf("%f", oandaCandles[index+1].Open) candleStrings[2] = fmt.Sprintf("%f", oandaCandles[index+1].High) candleStrings[3] = fmt.Sprintf("%f", oandaCandles[index+1].Low) candleStrings[4] = fmt.Sprintf("%f", oandaCandles[index+1].Close) } else { candleStrings[1] = fmt.Sprintf("%f", 0.0) candleStrings[2] = fmt.Sprintf("%f", 0.0) candleStrings[3] = fmt.Sprintf("%f", 0.0) candleStrings[4] = fmt.Sprintf("%f", 0.0) }*/ if index != -1 { candleStrings[1] = fmt.Sprintf("%f", oandaCandles[index].Open) candleStrings[2] = fmt.Sprintf("%f", oandaCandles[index].High) candleStrings[3] = fmt.Sprintf("%f", oandaCandles[index].Low) candleStrings[4] = fmt.Sprintf("%f", oandaCandles[index].Close) } else { candleStrings[1] = fmt.Sprintf("%f", 0.0) candleStrings[2] = fmt.Sprintf("%f", 0.0) candleStrings[3] = fmt.Sprintf("%f", 0.0) candleStrings[4] = fmt.Sprintf("%f", 0.0) } } candleStrings[0] = fmt.Sprintf("%d", iMain/1000) candleStrings[5] = fmt.Sprintf("%d", 0) hisData.Oanda = append(hisData.Oanda, candleStrings) } } done <- true }() } for i := 0; i < typeCount; i++ { <-done } output := getDownOutput(cb, &hisData) io.WriteString(w, output) } func symbolsHandler(w http.ResponseWriter, r *http.Request) { cb := r.FormValue("callback") //log.Println(cb) var symbols []SymbolData /*for i := markinfo.EURUSD; i < markinfo.CurrencyCount; i++ { var symbol SymbolData symbol.Symbol = i symbol.Name, _ = markinfo.SymbolName(i) symbol.PriceIncrement, _ = markinfo.SymbolUint(symbol.Name) symbol.Unit = int64(1 / symbol.PriceIncrement) if (symbol.Unit % 10) == 9 { symbol.Unit++ } symbols = append(symbols, symbol) }*/ symbol1 := SymbolData{Unit: 500, PriceIncrement: 0.001, Symbol: 20, Name: "XAGUSD"} symbols = append(symbols, symbol1) symbol2 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 38, Name: "EURMXN"} symbols = append(symbols, symbol2) symbol3 := SymbolData{Unit: 100, PriceIncrement: 0.01, Symbol: 22, Name: "OILUSD"} symbols = append(symbols, symbol3) symbol4 := SymbolData{Unit: 10000, PriceIncrement: 0.0001, Symbol: 26, Name: "EURCZK"} symbols = append(symbols, symbol4) symbol5 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 39, Name: "GBPMXN"} symbols = append(symbols, symbol5) symbol6 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 62, Name: "NZDCAD"} symbols = append(symbols, symbol6) symbol7 := SymbolData{Unit: 10, PriceIncrement: 0.01, Symbol: 21, Name: "XAUUSD"} symbols = append(symbols, symbol7) symbol8 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 56, Name: "EURZAR"} symbols = append(symbols, symbol8) symbol9 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 52, Name: "GBPSGD"} symbols = append(symbols, symbol9) symbol10 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 25, Name: "GBPCAD"} symbols = append(symbols, symbol10) symbol11 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 58, Name: "USDZAR"} symbols = append(symbols, symbol11) symbol12 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 50, Name: "USDSEK"} symbols = append(symbols, symbol12) symbol13 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 23, Name: "USDTRY"} symbols = append(symbols, symbol13) symbol14 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 6, Name: "NZDUSD"} symbols = append(symbols, symbol14) symbol15 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 18, Name: "USDMXN"} symbols = append(symbols, symbol15) symbol16 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 42, Name: "USDNOK"} symbols = append(symbols, symbol16) symbol17 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 32, Name: "EURHKD"} symbols = append(symbols, symbol17) symbol18 := SymbolData{Unit: 10000, PriceIncrement: 0.001, Symbol: 35, Name: "EURHUF"} symbols = append(symbols, symbol18) symbol19 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 55, Name: "GBPTRY"} symbols = append(symbols, symbol19) symbol20 := SymbolData{Unit: 10000, PriceIncrement: 0.0001, Symbol: 28, Name: "USDCZK"} symbols = append(symbols, symbol20) symbol21 := SymbolData{Unit: 10000, PriceIncrement: 0.001, Symbol: 37, Name: "USDHUF"} symbols = append(symbols, symbol21) symbol22 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 4, Name: "AUDUSD"} symbols = append(symbols, symbol22) symbol23 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 5, Name: "USDCAD"} symbols = append(symbols, symbol23) symbol24 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 60, Name: "AUDCHF"} symbols = append(symbols, symbol24) symbol25 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 29, Name: "EURDKK"} symbols = append(symbols, symbol25) symbol26 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 47, Name: "USDPLN"} symbols = append(symbols, symbol26) symbol27 := SymbolData{Unit: 10000, PriceIncrement: 0.0001, Symbol: 27, Name: "GBPCZK"} symbols = append(symbols, symbol27) symbol28 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 41, Name: "GBPNOK"} symbols = append(symbols, symbol28) symbol29 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 1, Name: "GBPUSD"} symbols = append(symbols, symbol29) symbol30 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 3, Name: "USDCHF"} symbols = append(symbols, symbol30) symbol31 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 51, Name: "EURSGD"} symbols = append(symbols, symbol31) symbol32 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 24, Name: "GBPAUD"} symbols = append(symbols, symbol32) symbol33 := SymbolData{Unit: 10000, PriceIncrement: 0.001, Symbol: 14, Name: "CHFJPY"} symbols = append(symbols, symbol33) symbol34 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 30, Name: "GBPDKK"} symbols = append(symbols, symbol34) symbol35 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 57, Name: "GBPZAR"} symbols = append(symbols, symbol35) symbol36 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 63, Name: "NZDCHF"} symbols = append(symbols, symbol36) symbol37 := SymbolData{Unit: 1, PriceIncrement: 0.1, Symbol: 68, Name: "UK100"} symbols = append(symbols, symbol37) symbol38 := SymbolData{Unit: 25, PriceIncrement: 0.1, Symbol: 70, Name: "SPX"} symbols = append(symbols, symbol38) symbol39 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 0, Name: "EURUSD"} symbols = append(symbols, symbol39) symbol40 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 12, Name: "GBPCHF"} symbols = append(symbols, symbol40) symbol41 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 46, Name: "GBPPLN"} symbols = append(symbols, symbol41) symbol42 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 7, Name: "EURGBP"} symbols = append(symbols, symbol42) symbol43 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 17, Name: "AUDCAD"} symbols = append(symbols, symbol43) symbol44 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 44, Name: "GBPNZD"} symbols = append(symbols, symbol44) symbol45 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 64, Name: "NZDSGD"} symbols = append(symbols, symbol45) symbol46 := SymbolData{Unit: 10000, PriceIncrement: 0.001, Symbol: 16, Name: "AUDJPY"} symbols = append(symbols, symbol46) symbol47 := SymbolData{Unit: 1, PriceIncrement: 0.1, Symbol: 74, Name: "STOXX50E"} symbols = append(symbols, symbol47) symbol48 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 53, Name: "USDSGD"} symbols = append(symbols, symbol48) symbol49 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 9, Name: "EURCHF"} symbols = append(symbols, symbol49) symbol50 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 40, Name: "EURNOK"} symbols = append(symbols, symbol50) symbol51 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 43, Name: "EURNZD"} symbols = append(symbols, symbol51) symbol52 := SymbolData{Unit: 10000, PriceIncrement: 0.001, Symbol: 59, Name: "NZDJPY"} symbols = append(symbols, symbol52) symbol53 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 34, Name: "USDHKD"} symbols = append(symbols, symbol53) symbol54 := SymbolData{Unit: 10000, PriceIncrement: 0.001, Symbol: 2, Name: "USDJPY"} symbols = append(symbols, symbol54) symbol55 := SymbolData{Unit: 10000, PriceIncrement: 0.001, Symbol: 15, Name: "CADJPY"} symbols = append(symbols, symbol55) symbol56 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 45, Name: "EURPLN"} symbols = append(symbols, symbol56) symbol57 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 33, Name: "GBPHKD"} symbols = append(symbols, symbol57) symbol58 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 48, Name: "EURSEK"} symbols = append(symbols, symbol58) symbol59 := SymbolData{Unit: 1, PriceIncrement: 0.1, Symbol: 73, Name: "FCHI"} symbols = append(symbols, symbol59) symbol60 := SymbolData{Unit: 10, PriceIncrement: 0.1, Symbol: 71, Name: "NDX"} symbols = append(symbols, symbol60) symbol61 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 10, Name: "EURAUD"} symbols = append(symbols, symbol61) symbol62 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 19, Name: "AUDNZD"} symbols = append(symbols, symbol62) symbol63 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 54, Name: "EURTRY"} symbols = append(symbols, symbol63) symbol64 := SymbolData{Unit: 10000, PriceIncrement: 0.001, Symbol: 36, Name: "GBPHUF"} symbols = append(symbols, symbol64) symbol65 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 49, Name: "GBPSEK"} symbols = append(symbols, symbol65) symbol66 := SymbolData{Unit: 2.5, PriceIncrement: 0.1, Symbol: 72, Name: "GDAXI"} symbols = append(symbols, symbol66) symbol67 := SymbolData{Unit: 10000, PriceIncrement: 0.001, Symbol: 8, Name: "EURJPY"} symbols = append(symbols, symbol67) symbol68 := SymbolData{Unit: 10000, PriceIncrement: 0.001, Symbol: 13, Name: "GBPJPY"} symbols = append(symbols, symbol68) symbol69 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 11, Name: "EURCAD"} symbols = append(symbols, symbol69) symbol70 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 61, Name: "CADCHF"} symbols = append(symbols, symbol70) symbol71 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 31, Name: "USDDKK"} symbols = append(symbols, symbol71) symbol72 := SymbolData{Unit: 1, PriceIncrement: 1, Symbol: 69, Name: "WS30"} symbols = append(symbols, symbol72) symbol73 := SymbolData{Unit: 10000, PriceIncrement: 1e-05, Symbol: 65, Name: "LTCUSD"} symbols = append(symbols, symbol73) symbol74 := SymbolData{Unit: 10000, PriceIncrement: 0.001, Symbol: 66, Name: "BTCUSD"} symbols = append(symbols, symbol74) b, _ := json.Marshal(symbols) output := fmt.Sprintf("if (%s) %s(%s)\n", cb, cb, string(b)) io.WriteString(w, output) } /* func testHandler(w http.ResponseWriter, r *http.Request) { insId := r.FormValue("insid") period := r.FormValue("period") st := r.FormValue("st") et := r.FormValue("et") log.Println(insId, period, st, et) periodId, ok := market.PeriodIdMap[period] if !ok { http.Error(w, "webserver doesn't support period", http.StatusBadRequest) return } st64, _ := strconv.ParseInt(st, 10, 64) et64, _ := strconv.ParseInt(et, 10, 64) fnames, err := clientDown.GetHisEx(insId, periodId, st64, et64, false) if err != nil { http.Error(w, "webserver can't get data", http.StatusBadRequest) return } sort.Sort(byDlInfo(fnames)) var output string for i, v := range fnames { output += fmt.Sprintf("%d %s %s %d %d %d", i, v.Fname, v.Reply.Url, v.Reply.St, v.Reply.Et, v.Reply.N) } io.WriteString(w, output) } */ type gzipResponseWriter struct { io.Writer http.ResponseWriter } func (w gzipResponseWriter) Write(b []byte) (int, error) { return w.Writer.Write(b) } func (w gzipResponseWriter) Flush() { w.Writer.(*gzip.Writer).Flush() w.ResponseWriter.(http.Flusher).Flush() } func makeGzipHandler(fn http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { fn(w, r) return } w.Header().Set("Content-Encoding", "gzip") w.Header().Set("Content-Type", "text/javascript") gz := gzip.NewWriter(w) defer gz.Close() fn(gzipResponseWriter{Writer: gz, ResponseWriter: w}, r) } } func main() { runtime.GOMAXPROCS(runtime.NumCPU()) conf, err := readConf() if err != nil { flag.Parse() } else { *saddr1 = conf.Saddr1 *saddr2 = conf.Saddr2 *saddr3 = conf.Saddr3 *saddr4 = conf.Saddr4 } err = connectServer() if err != nil { log.Fatal("connect server", err) } //go updateTick() s := &http.Server{ Addr: ":6062", ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, MaxHeaderBytes: 1 << 20, } //http.HandleFunc("/tickdata", tickHandler) //http.HandleFunc("/api.php", makeGzipHandler(downHandler)) //http.HandleFunc("/symbols", symbolsHandler) http.HandleFunc("/daydata", dayHandler) http.HandleFunc("/h24data", h24Handler) //http.HandleFunc("/test", testHandler) log.Fatal(s.ListenAndServe()) }