wr 5 سال پیش
والد
کامیت
0d8ee226e6

+ 90 - 0
markinfo/const.go

@@ -105,6 +105,36 @@ const (
 	YCCUSDT
 	BTCSUSDT
 	DCRUSDT
+	BNTUSDT
+	BNTBTC
+	SCTCUSDT
+	SCTCBTC
+	YCCBTC
+	YCCETH
+	JBUSDT
+	JBBTC
+	JBETH
+	OPTCUSDT
+	OPTCBTC
+	OPTCETH
+	BCCETH
+	ZECETH
+	ETCETH
+	LTCETH
+	STILT
+	ITVBUSDT
+	ITVBBTC
+	ITVBETH
+	BTYETH
+	FHUSDT
+	CWVUSDT
+	FHETH
+	TMCETH
+	FANSUSDT
+	FANSBTC
+	FANSETH
+	WTBWTC
+	CNSUSDT
 	CurrencyCount
 	UK100
 	WS30
@@ -273,6 +303,36 @@ var symbols = map[int]string{
 	YCCUSDT:       "YCCUSDT",
 	BTCSUSDT:      "BTCSUSDT",
 	DCRUSDT:       "DCRUSDT",
+	BNTUSDT:       "BNTUSDT",
+	BNTBTC:        "BNTBTC",
+	SCTCUSDT:      "SCTCUSDT",
+	SCTCBTC:       "SCTCBTC",
+	YCCBTC:        "YCCBTC",
+	YCCETH:        "YCCETH",
+	JBUSDT:        "JBUSDT",
+	JBBTC:         "JBBTC",
+	JBETH:         "JBETH",
+	OPTCUSDT:      "OPTCUSDT",
+	OPTCBTC:       "OPTCBTC",
+	OPTCETH:       "OPTCETH",
+	BCCETH:        "BCCETH",
+	ZECETH:        "ZECETH",
+	ETCETH:        "ETCETH",
+	LTCETH:        "LTCETH",
+	STILT:         "STILT",
+	ITVBUSDT:      "ITVBUSDT",
+	ITVBBTC:       "ITVBBTC",
+	ITVBETH:       "ITVBETH",
+	BTYETH:        "BTYETH",
+	FHUSDT:        "FHUSDT",
+	CWVUSDT:       "CWVUSDT",
+	FHETH:         "FHETH",
+	TMCETH:        "TMCETH",
+	FANSUSDT:      "FANSUSDT",
+	FANSBTC:       "FANSBTC",
+	FANSETH:       "FANSETH",
+	WTBWTC:        "WTBWTC",
+	CNSUSDT:       "CNSUSDT",
 	UK100:         "UK100",
 	WS30:          "WS30",
 	SPX:           "SPX",
@@ -440,6 +500,36 @@ var symbolUnitInt = map[int]float64{
 	YCCUSDT:       0.00001,
 	BTCSUSDT:      0.00001,
 	DCRUSDT:       0.00001,
+	BNTUSDT:       0.00001,
+	BNTBTC:        0.00001,
+	SCTCUSDT:      0.00001,
+	SCTCBTC:       0.00001,
+	YCCBTC:        0.00001,
+	YCCETH:        0.00001,
+	JBUSDT:        0.00001,
+	JBBTC:         0.00001,
+	JBETH:         0.00001,
+	OPTCUSDT:      0.00001,
+	OPTCBTC:       0.00001,
+	OPTCETH:       0.00001,
+	BCCETH:        0.00001,
+	ZECETH:        0.00001,
+	ETCETH:        0.00001,
+	LTCETH:        0.00001,
+	STILT:         0.00001,
+	ITVBUSDT:      0.00001,
+	ITVBBTC:       0.00001,
+	ITVBETH:       0.00001,
+	BTYETH:        0.00001,
+	FHUSDT:        0.00001,
+	CWVUSDT:       0.00001,
+	FHETH:         0.00001,
+	TMCETH:        0.00001,
+	FANSUSDT:      0.00001,
+	FANSBTC:       0.00001,
+	FANSETH:       0.00001,
+	WTBWTC:        0.00001,
+	CNSUSDT:       0.00001,
 	UK100:         0.1,
 	WS30:          0.1,
 	SPX:           0.1,

+ 131 - 0
server/cmd/test/main.go

@@ -0,0 +1,131 @@
+// main.go
+package main
+
+import (
+	"bufio"
+	"flag"
+	"fmt"
+	"io"
+	"log"
+	"os"
+	//"strconv"
+	"strings"
+	//"tickserver/server/market"
+	"time"
+)
+
+func main() {
+	loc, err := time.LoadLocation("Europe/Athens")
+	flag.Parse()
+	n := flag.NArg()
+	if n != 1 {
+		log.Println("must input file name", n)
+		return
+	}
+	file := flag.Arg(0)
+	fi, err := os.Open(file)
+	if err != nil {
+		fmt.Printf("Error: %s\n", err)
+		return
+	}
+	defer fi.Close()
+	files := strings.Split(file, ".")
+	br := bufio.NewReader(fi)
+	f, err := os.Create(files[0] + ".log")
+	if err != nil {
+		fmt.Printf("Error: %s\n", err)
+		return
+	}
+	defer f.Close()
+	bw := bufio.NewWriter(f)
+	for {
+		a, _, c := br.ReadLine()
+		if c == io.EOF {
+			break
+		}
+		datas := strings.Split(string(a), ",")
+		if len(datas) != 6 {
+			break
+		}
+		var year, month, day, hour, minute int
+		fmt.Sscanf(datas[0], "%04d.%02d.%02d %02d:%02d", &year, &month, &day, &hour, &minute)
+		t := time.Date(year, time.Month(month), day, hour, minute, 0, 0, loc)
+		//log.Println(t.Unix())
+		ut := time.Unix(t.Unix(), 0)
+		line := files[0] + ","
+		line += fmt.Sprintf("%04d%02d%02d,%02d%02d%02d", ut.UTC().Year(), ut.UTC().Month(), ut.UTC().Day(), ut.UTC().Hour(), ut.UTC().Minute(), ut.UTC().Second())
+		line += "," + datas[1] + "," + datas[2] + "," + datas[3] + "," + datas[4] + "," + datas[5]
+		//log.Println(line)
+		fmt.Fprintln(bw, line)
+	}
+	bw.Flush()
+}
+
+/*
+// main.go
+package main
+
+import (
+	"bufio"
+	"flag"
+	"fmt"
+	"io"
+	"log"
+	"os"
+	"strconv"
+	"strings"
+	"tickserver/server/market"
+	"time"
+)
+
+func main() {
+	flag.Parse()
+	n := flag.NArg()
+	if n != 1 {
+		log.Println("must input file name", n)
+		return
+	}
+	file := flag.Arg(0)
+	fi, err := os.Open(file)
+	if err != nil {
+		fmt.Printf("Error: %s\n", err)
+		return
+	}
+	defer fi.Close()
+	files := strings.Split(file, ".")
+	br := bufio.NewReader(fi)
+	var candles []market.Candle
+	for {
+		var candle market.Candle
+		a, _, c := br.ReadLine()
+		if c == io.EOF {
+			break
+		}
+		datas := strings.Split(string(a), ",")
+		if datas[0] == files[0] {
+			var year, month, day, hour, minute, second int
+			fmt.Sscanf(datas[1], "%04d%02d%02d", &year, &month, &day)
+			fmt.Sscanf(datas[2], "%02d%02d%02d", &hour, &minute, &second)
+			t := time.Date(year, time.Month(month), day, hour, minute, second, 0, time.UTC)
+			candle.Timestamp = t.Unix() * 1000
+			candle.Open, _ = strconv.ParseFloat(datas[3], 64)
+			candle.High, _ = strconv.ParseFloat(datas[4], 64)
+			candle.Low, _ = strconv.ParseFloat(datas[5], 64)
+			candle.Close, _ = strconv.ParseFloat(datas[6], 64)
+			candle.RealVolums, _ = strconv.ParseFloat(datas[7], 64)
+			candle.TickVolums, _ = strconv.ParseFloat(datas[7], 64)
+			candles = append(candles, candle)
+		}
+	}
+	market.SaveCandlesTmp("fzmnew/mt4", "mt4_"+files[0], candles, market.M1, false)
+	r := market.NewCandleBuf(candles)
+	candlesm5, _ := market.ConvPeriod(r, "mt4_"+files[0], market.M5)
+	market.SaveCandlesTmp("fzmnew/mt4", "mt4_"+files[0], candlesm5, market.M5, false)
+	r = market.NewCandleBuf(candlesm5)
+	candlesh1, _ := market.ConvPeriod(r, "mt4_"+files[0], market.H1)
+	market.SaveCandlesTmp("fzmnew/mt4", "mt4_"+files[0], candlesh1, market.H1, false)
+	r = market.NewCandleBuf(candlesh1)
+	candlesd1, _ := market.ConvPeriod(r, "mt4_"+files[0], market.D1)
+	market.SaveCandlesTmp("fzmnew/mt4", "mt4_"+files[0], candlesd1, market.D1, false)
+}
+*/

+ 306 - 2
server/cmd/webproxy/main.go

@@ -8,6 +8,7 @@ import (
 	"flag"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"log"
 	"net/http"
 	"os"
@@ -23,6 +24,24 @@ import (
 	"tickserver/server/market"
 )
 
+type Hadax struct {
+	Status string  `json:"status"`
+	Ch     string  `json:"ch"`
+	Ts     int64   `json:"ts"`
+	Data   []Kdata `json:"data"`
+}
+
+type Kdata struct {
+	Id     int64   `json:"id"`
+	Open   float64 `json:"open"`
+	Close  float64 `json:"close"`
+	Low    float64 `json:"low"`
+	High   float64 `json:"high"`
+	Amount float64 `json:"amount"`
+	Vol    float64 `json:"vol"`
+	Count  int64   `json:"count"`
+}
+
 type RealTick struct {
 	tg base.TickGo
 	//tgCh <-chan base.TickGo
@@ -129,91 +148,296 @@ func readConf() (*Conf, error) {
 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.Open = fmt.Sprintf("%.4f", stk.Open)
 		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.Open = fmt.Sprintf("%.5f", stk.Open)
 		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.Open = fmt.Sprintf("%.6f", stk.Open)
 		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.Open = fmt.Sprintf("%.5f", stk.Open)
 		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.Open = fmt.Sprintf("%.6f", stk.Open)
 		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.Open = fmt.Sprintf("%.2f", stk.Open)
 		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.Open = fmt.Sprintf("%.2f", stk.Open)
 		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.Open = fmt.Sprintf("%.2f", stk.Open)
 		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.Open = fmt.Sprintf("%.2f", stk.Open)
 		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.Open = fmt.Sprintf("%.2f", stk.Open)
 		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.Open = fmt.Sprintf("%.2f", stk.Open)
 		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
+		sstk.Open = fmt.Sprintf("%.6f", stk.Open)
+		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_BTYUSDT":
+		sstk.Open = fmt.Sprintf("%.4f", stk.Open)
 		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.Open = fmt.Sprintf("%.2f", stk.Open)
 		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.Open = fmt.Sprintf("%.6f", stk.Open)
 		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.Open = fmt.Sprintf("%.4f", stk.Open)
 		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.Open = fmt.Sprintf("%.2f", stk.Open)
+		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_BNTUSDT":
+		sstk.Open = fmt.Sprintf("%.4f", stk.Open)
+		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("%.0f", stk.Volume)
+	case "bty_BNTBTC":
+		sstk.Open = fmt.Sprintf("%.8f", stk.Open)
+		sstk.Last = fmt.Sprintf("%.8f", stk.Last)
+		sstk.High = fmt.Sprintf("%.8f", stk.High)
+		sstk.Low = fmt.Sprintf("%.8f", stk.Low)
+		sstk.Volume = fmt.Sprintf("%.0f", stk.Volume)
+	case "bty_SCTCUSDT":
+		sstk.Open = fmt.Sprintf("%.6f", stk.Open)
+		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_SCTCBTC":
+		sstk.Open = fmt.Sprintf("%.8f", stk.Open)
+		sstk.Last = fmt.Sprintf("%.8f", stk.Last)
+		sstk.High = fmt.Sprintf("%.8f", stk.High)
+		sstk.Low = fmt.Sprintf("%.8f", stk.Low)
+		sstk.Volume = fmt.Sprintf("%.0f", stk.Volume)
+	case "bty_YCCBTC":
+		sstk.Open = fmt.Sprintf("%.8f", stk.Open)
+		sstk.Last = fmt.Sprintf("%.8f", stk.Last)
+		sstk.High = fmt.Sprintf("%.8f", stk.High)
+		sstk.Low = fmt.Sprintf("%.8f", stk.Low)
+		sstk.Volume = fmt.Sprintf("%.0f", stk.Volume)
+	case "bty_YCCETH":
+		sstk.Open = fmt.Sprintf("%.8f", stk.Open)
+		sstk.Last = fmt.Sprintf("%.8f", stk.Last)
+		sstk.High = fmt.Sprintf("%.8f", stk.High)
+		sstk.Low = fmt.Sprintf("%.8f", stk.Low)
+		sstk.Volume = fmt.Sprintf("%.0f", stk.Volume)
+	case "bty_JBUSDT":
+		sstk.Open = fmt.Sprintf("%.4f", stk.Open)
+		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("%.0f", stk.Volume)
+	case "bty_JBBTC":
+		sstk.Open = fmt.Sprintf("%.8f", stk.Open)
+		sstk.Last = fmt.Sprintf("%.8f", stk.Last)
+		sstk.High = fmt.Sprintf("%.8f", stk.High)
+		sstk.Low = fmt.Sprintf("%.8f", stk.Low)
+		sstk.Volume = fmt.Sprintf("%.0f", stk.Volume)
+	case "bty_JBETH":
+		sstk.Open = fmt.Sprintf("%.6f", stk.Open)
+		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_OPTCUSDT":
+		sstk.Open = fmt.Sprintf("%.4f", stk.Open)
+		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("%.0f", stk.Volume)
+	case "bty_OPTCBTC":
+		sstk.Open = fmt.Sprintf("%.8f", stk.Open)
+		sstk.Last = fmt.Sprintf("%.8f", stk.Last)
+		sstk.High = fmt.Sprintf("%.8f", stk.High)
+		sstk.Low = fmt.Sprintf("%.8f", stk.Low)
+		sstk.Volume = fmt.Sprintf("%.0f", stk.Volume)
+	case "bty_OPTCETH":
+		sstk.Open = fmt.Sprintf("%.8f", stk.Open)
+		sstk.Last = fmt.Sprintf("%.8f", stk.Last)
+		sstk.High = fmt.Sprintf("%.8f", stk.High)
+		sstk.Low = fmt.Sprintf("%.8f", stk.Low)
+		sstk.Volume = fmt.Sprintf("%.0f", stk.Volume)
+	case "bty_BTCETH":
+		sstk.Open = fmt.Sprintf("%.4f", stk.Open)
+		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_BCCETH":
+		sstk.Open = fmt.Sprintf("%.4f", stk.Open)
+		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_ZECETH":
+		sstk.Open = fmt.Sprintf("%.3f", stk.Open)
+		sstk.Last = fmt.Sprintf("%.3f", stk.Last)
+		sstk.High = fmt.Sprintf("%.3f", stk.High)
+		sstk.Low = fmt.Sprintf("%.3f", stk.Low)
+		sstk.Volume = fmt.Sprintf("%.5f", stk.Volume)
+	case "bty_ETCETH":
+		sstk.Open = fmt.Sprintf("%.2f", stk.Open)
+		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("%.6f", stk.Volume)
+	case "bty_LTCETH":
+		sstk.Open = fmt.Sprintf("%.3f", stk.Open)
+		sstk.Last = fmt.Sprintf("%.3f", stk.Last)
+		sstk.High = fmt.Sprintf("%.3f", stk.High)
+		sstk.Low = fmt.Sprintf("%.3f", stk.Low)
+		sstk.Volume = fmt.Sprintf("%.5f", stk.Volume)
+	case "bty_STILT":
+		sstk.Open = fmt.Sprintf("%.2f", stk.Open)
 		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_ITVBUSDT":
+		sstk.Open = fmt.Sprintf("%.4f", stk.Open)
+		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("%.0f", stk.Volume)
+	case "bty_ITVBBTC":
+		sstk.Open = fmt.Sprintf("%.8f", stk.Open)
+		sstk.Last = fmt.Sprintf("%.8f", stk.Last)
+		sstk.High = fmt.Sprintf("%.8f", stk.High)
+		sstk.Low = fmt.Sprintf("%.8f", stk.Low)
+		sstk.Volume = fmt.Sprintf("%.0f", stk.Volume)
+	case "bty_ITVBETH":
+		sstk.Open = fmt.Sprintf("%.8f", stk.Open)
+		sstk.Last = fmt.Sprintf("%.8f", stk.Last)
+		sstk.High = fmt.Sprintf("%.8f", stk.High)
+		sstk.Low = fmt.Sprintf("%.8f", stk.Low)
+		sstk.Volume = fmt.Sprintf("%.0f", stk.Volume)
+	case "bty_BTYETH":
+		sstk.Open = fmt.Sprintf("%.8f", stk.Open)
+		sstk.Last = fmt.Sprintf("%.8f", stk.Last)
+		sstk.High = fmt.Sprintf("%.8f", stk.High)
+		sstk.Low = fmt.Sprintf("%.8f", stk.Low)
+		sstk.Volume = fmt.Sprintf("%.0f", stk.Volume)
+	case "bty_FHUSDT":
+		sstk.Open = fmt.Sprintf("%.5f", stk.Open)
+		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("%.1f", stk.Volume)
+	case "bty_CWVUSDT":
+		sstk.Open = fmt.Sprintf("%.6f", stk.Open)
+		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_FHETH":
+		sstk.Open = fmt.Sprintf("%.7f", stk.Open)
+		sstk.Last = fmt.Sprintf("%.7f", stk.Last)
+		sstk.High = fmt.Sprintf("%.7f", stk.High)
+		sstk.Low = fmt.Sprintf("%.7f", stk.Low)
+		sstk.Volume = fmt.Sprintf("%.1f", stk.Volume)
+	case "bty_TMCETH":
+		sstk.Open = fmt.Sprintf("%.7f", stk.Open)
+		sstk.Last = fmt.Sprintf("%.7f", stk.Last)
+		sstk.High = fmt.Sprintf("%.7f", stk.High)
+		sstk.Low = fmt.Sprintf("%.7f", stk.Low)
+		sstk.Volume = fmt.Sprintf("%.1f", stk.Volume)
+	case "bty_FANSUSDT":
+		sstk.Open = fmt.Sprintf("%.5f", stk.Open)
+		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("%.1f", stk.Volume)
+	case "bty_FANSBTC":
+		sstk.Open = fmt.Sprintf("%.7f", stk.Open)
+		sstk.Last = fmt.Sprintf("%.7f", stk.Last)
+		sstk.High = fmt.Sprintf("%.7f", stk.High)
+		sstk.Low = fmt.Sprintf("%.7f", stk.Low)
+		sstk.Volume = fmt.Sprintf("%.1f", stk.Volume)
+	case "bty_FANSETH":
+		sstk.Open = fmt.Sprintf("%.7f", stk.Open)
+		sstk.Last = fmt.Sprintf("%.7f", stk.Last)
+		sstk.High = fmt.Sprintf("%.7f", stk.High)
+		sstk.Low = fmt.Sprintf("%.7f", stk.Low)
+		sstk.Volume = fmt.Sprintf("%.1f", stk.Volume)
+	case "bty_WTBWTC":
+		sstk.Open = fmt.Sprintf("%.7f", stk.Open)
+		sstk.Last = fmt.Sprintf("%.7f", stk.Last)
+		sstk.High = fmt.Sprintf("%.7f", stk.High)
+		sstk.Low = fmt.Sprintf("%.7f", stk.Low)
+		sstk.Volume = fmt.Sprintf("%.1f", stk.Volume)
+	case "bty_CNSUSDT":
+		sstk.Open = fmt.Sprintf("%.5f", stk.Open)
+		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("%.1f", stk.Volume)
 	default:
 	}
 
@@ -262,6 +486,14 @@ func h24Handler(w http.ResponseWriter, r *http.Request) {
 	var candles []client.Candle
 	insId := typ + "_" + symbol
 	bufcandles, err := clientDown.GetLastCandles(insId, market.H1, 24)
+	/*if insId == "bty_BTCUSDT" {
+		for i, _ := range bufcandles {
+			if bufcandles[i].Open == 7000 && (bufcandles[i].Timestamp >= 1528941600000 && bufcandles[i].Timestamp <= 1528945200000) {
+				bufcandles[i].High = 6468.7001953125
+				bufcandles[i].Open = 6269.2998046875
+			}
+		}
+	}*/
 	/*for i, _ := range bufcandles {
 		if insId == "bty_ETHUSDT" {
 			if bufcandles[i].Timestamp >= 1524031200000 && bufcandles[i].Timestamp <= 1524031200000 {
@@ -353,6 +585,31 @@ func h24Handler(w http.ResponseWriter, r *http.Request) {
 
 		var stk SpecialTick
 		if len(candles) > 0 {
+			candlesOk := make([]client.Candle, len(candles))
+			begin, end := getTimeRange()
+			begin *= 1000
+			end *= 1000
+			pos := 0
+			for i := 0; i < len(candles); i++ {
+				if candles[i].Timestamp >= begin && candles[i].Timestamp <= end {
+					candlesOk[pos] = candles[i]
+					pos++
+				}
+			}
+			if pos == 0 {
+				candlesHadax := getHadax(strings.ToLower(symbol), "60min", 24)
+				if len(candlesHadax) > 0 {
+					candles = candlesHadax[:]
+				} else {
+					leng := len(candles)
+					candles = candles[leng-1 : leng]
+					candles[0].Open = candles[0].Close
+					candles[0].High = candles[0].Close
+					candles[0].Low = candles[0].Close
+				}
+			} else {
+				candles = candlesOk[:pos]
+			}
 			stk.Low = candles[0].Low
 			stk.Open = candles[0].Open
 			stk.Timestamp = candles[0].Timestamp / 1000
@@ -1207,6 +1464,53 @@ func makeGzipHandler(fn http.HandlerFunc) http.HandlerFunc {
 	}
 }
 
+func getHadax(sym, per string, size int) []client.Candle {
+	url := fmt.Sprintf("https://api.hadax.com/market/history/kline?period=%s&size=%d&symbol=%s", per, size, sym)
+	response, err := http.Get(url)
+	if err != nil {
+		log.Println(err)
+		return nil
+	}
+	body, err := ioutil.ReadAll(response.Body)
+	if err != nil {
+		log.Println(err)
+		return nil
+	}
+	var data Hadax
+	err = json.Unmarshal(body, &data)
+	if err != nil {
+		log.Println(err)
+		return nil
+	}
+	response.Body.Close()
+	//log.Println(data)
+	datalen := len(data.Data)
+	if datalen > 0 {
+		candles := make([]client.Candle, datalen)
+		for i := datalen - 1; i >= 0; i-- {
+			candles[(datalen-1)-i].Timestamp = data.Data[i].Id * 1000
+			if per == "1day" {
+				candles[(datalen-1)-i].Timestamp += 8 * 60 * 60 * 1000
+			}
+			candles[(datalen-1)-i].Open = data.Data[i].Open
+			candles[(datalen-1)-i].High = data.Data[i].High
+			candles[(datalen-1)-i].Low = data.Data[i].Low
+			candles[(datalen-1)-i].Close = data.Data[i].Close
+			candles[(datalen-1)-i].RealVolums = data.Data[i].Amount
+			candles[(datalen-1)-i].TickVolums = float64(data.Data[i].Count)
+		}
+		return candles
+	}
+	return nil
+}
+
+func getTimeRange() (begin int64, end int64) {
+	now := time.Now().Unix()
+	end = now - now%3600
+	begin = end - 24*3600
+	return
+}
+
 func main() {
 	runtime.GOMAXPROCS(runtime.NumCPU())
 	conf, err := readConf()

+ 11 - 3
server/cmd/webproxys/main.go

@@ -193,6 +193,13 @@ func getData(symbol, period, action, count, out, cb, te, ts string, style int) (
 
 	var bufferedCandles []client.Candle
 	bufferedCandles, _ = clientDown.GetLastCandles(myInsId, periodId, 0x7fffffff)
+	/*if myInsId == "bty_BTCUSDT" && periodId == market.D1 {
+		for i, _ := range bufferedCandles {
+			if bufferedCandles[i].Timestamp == 1528934400000 {
+				bufferedCandles[i].High = 6625.7998046875
+			}
+		}
+	}*/
 	/*bNormal := false
 	for i, _ := range bufferedCandles {
 		if myInsId == "bty_ETHUSDT" {
@@ -1203,7 +1210,8 @@ func main() {
 
 	s := &http.Server{
 		//Addr: ":3062",
-		Addr: ":4062",
+		//Addr: ":4062",
+		Addr: ":7062",
 		//Addr:           ":9062",
 		ReadTimeout:    10 * time.Second,
 		WriteTimeout:   10 * time.Second,
@@ -1211,7 +1219,7 @@ func main() {
 	}
 	http.HandleFunc("/kdata", makeGzipHandler(kdataHandler))
 	http.HandleFunc("/tdata", makeGzipHandler(tdataHandler))
-	log.Fatal(s.ListenAndServeTLS("214341259320977.pem", "214341259320977.key"))
-	//log.Fatal(s.ListenAndServe())
+	//log.Fatal(s.ListenAndServeTLS("214341259320977.pem", "214341259320977.key"))
+	log.Fatal(s.ListenAndServe())
 	//log.Fatal(s.ListenAndServeTLS("licai20170620.pem", "licai20170620.key"))
 }

+ 340 - 73
server/tick/ds_bty.go

@@ -7,10 +7,11 @@ package tick
 import (
 	"database/sql"
 	"encoding/json"
-	"errors"
+	//"errors"
 	"fmt"
 	"io/ioutil"
 	//"log"
+	//"bytes"
 	"net/http"
 	"strconv"
 	"time"
@@ -37,6 +38,88 @@ var btyInss = []int{
 	markinfo.BTSUSDT,
 	markinfo.SCUSDT,
 	markinfo.DCRUSDT,
+	markinfo.BNTUSDT,
+	markinfo.BNTBTC,
+	markinfo.SCTCUSDT,
+	markinfo.SCTCBTC,
+	markinfo.YCCUSDT,
+	markinfo.YCCBTC,
+	markinfo.YCCETH,
+	markinfo.JBUSDT,
+	markinfo.JBBTC,
+	markinfo.JBETH,
+	markinfo.OPTCUSDT,
+	markinfo.OPTCBTC,
+	markinfo.OPTCETH,
+	markinfo.BTCETH,
+	markinfo.BCCETH,
+	markinfo.ZECETH,
+	markinfo.ETCETH,
+	markinfo.LTCETH,
+	markinfo.STILT,
+	markinfo.ITVBUSDT,
+	markinfo.ITVBBTC,
+	markinfo.ITVBETH,
+	markinfo.BTYETH,
+	markinfo.FHUSDT,
+	markinfo.CWVUSDT,
+	markinfo.FHETH,
+	markinfo.TMCETH,
+	markinfo.FANSUSDT,
+	markinfo.FANSBTC,
+	markinfo.FANSETH,
+	markinfo.WTBWTC,
+	markinfo.CNSUSDT,
+}
+
+var inss = map[int]string{
+	markinfo.ETHBTC:   "ETH_BTC",
+	markinfo.ETCBTC:   "ETC_BTC",
+	markinfo.ZECBTC:   "ZEC_BTC",
+	markinfo.LTCBTC:   "LTC_BTC",
+	markinfo.BCCBTC:   "BCC_BTC",
+	markinfo.ETHUSDT:  "ETH_USDT",
+	markinfo.ETCUSDT:  "ETC_USDT",
+	markinfo.ZECUSDT:  "ZEC_USDT",
+	markinfo.LTCUSDT:  "LTC_USDT",
+	markinfo.BCCUSDT:  "BCC_USDT",
+	markinfo.BTCUSDT:  "BTC_USDT",
+	markinfo.BTYUSDT:  "BTY_USDT",
+	markinfo.BTSUSDT:  "BTS_USDT",
+	markinfo.SCUSDT:   "SC_USDT",
+	markinfo.DCRUSDT:  "DCR_USDT",
+	markinfo.BNTUSDT:  "BNT_USDT",
+	markinfo.BNTBTC:   "BNT_BTC",
+	markinfo.SCTCUSDT: "SCTC_USDT",
+	markinfo.SCTCBTC:  "SCTC_BTC",
+	markinfo.YCCUSDT:  "YCC_USDT",
+	markinfo.YCCBTC:   "YCC_BTC",
+	markinfo.YCCETH:   "YCC_ETH",
+	markinfo.JBUSDT:   "JB_USDT",
+	markinfo.JBBTC:    "JB_BTC",
+	markinfo.JBETH:    "JB_ETH",
+	markinfo.OPTCUSDT: "OPTC_USDT",
+	markinfo.OPTCBTC:  "OPTC_BTC",
+	markinfo.OPTCETH:  "OPTC_ETH",
+	markinfo.BTCETH:   "BTC_ETH",
+	markinfo.BCCETH:   "BCC_ETH",
+	markinfo.ZECETH:   "ZEC_ETH",
+	markinfo.ETCETH:   "ETC_ETH",
+	markinfo.LTCETH:   "LTC_ETH",
+	markinfo.STILT:    "ST_ILT",
+	markinfo.ITVBUSDT: "ITVB_USDT",
+	markinfo.ITVBBTC:  "ITVB_BTC",
+	markinfo.ITVBETH:  "ITVB_ETH",
+	markinfo.BTYETH:   "BTY_ETH",
+	markinfo.FHUSDT:   "FH_USDT",
+	markinfo.CWVUSDT:  "CWV_USDT",
+	markinfo.FHETH:    "FH_ETH",
+	markinfo.TMCETH:   "TMC_ETH",
+	markinfo.FANSUSDT: "FANS_USDT",
+	markinfo.FANSBTC:  "FANS_BTC",
+	markinfo.FANSETH:  "FANS_ETH",
+	markinfo.WTBWTC:   "WTB_WTC",
+	markinfo.CNSUSDT:  "CNS_USDT",
 }
 
 var btyTable = "inss_lastoffsets"
@@ -92,7 +175,7 @@ func (bds *BtyDS) Run() {
 	for {
 		mk, err := bty_reader.Read()
 		if err != nil {
-			fmt.Println(err)
+			fmt.Println("1", err)
 		}
 		//log.Println("save fuck")
 		bds.Save(mk)
@@ -131,29 +214,29 @@ func (bds *BtyDS) getData(instrumentId, offset int64) {
 
 func GetEthTickbyPage(instrumentId, offset int64, cb func(*Market)) (int64, error) {
 	symbol, _ := markinfo.SymbolName(int(instrumentId))
-	url := "http://10.0.1.5:45656/tender/default/kline?symbol=" + symbol + "&offset=" + fmt.Sprintf("%d", offset) + "&limit=100"
-	//url := "http://65.52.167.178:45656/forward?symbol=" + symbol + "&offset=" + fmt.Sprintf("%d", offset) + "&limit=100"
+	//url := "http://122.224.124.250:10115/tender/default/kline?symbol=" + symbol + "&offset=" + fmt.Sprintf("%d", offset) + "&limit=100"
+	//url := "http://10.0.1.5:45659/tender/default/kline?symbol=" + symbol + "&offset=" + fmt.Sprintf("%d", offset) + "&limit=100"
+	url := "http://10.0.1.177:80/tender/default/kline?symbol=" + symbol + "&offset=" + fmt.Sprintf("%d", offset) + "&limit=100"
 	response, err := http.Get(url)
 	if err != nil {
-		//log.Println("f1", url, err)
 		return offset, err
 	}
 	defer response.Body.Close()
 	body, err := ioutil.ReadAll(response.Body)
 	if err != nil {
-		//log.Println("f2", url, err)
+		//fmt.Println("f2", url, err)
 		return offset, err
 	}
 	var data map[string]interface{}
 	err = json.Unmarshal(body, &data)
 	if err != nil {
-		//log.Println("f3", url, err)
+		//fmt.Println("f3", url, err)
 		return offset, err
 	}
 	//fmt.Println(url)
 	dataticks, ok := data["result"].([]interface{})
 	if !ok {
-		//log.Println("GetEthTickbyPage1", url, string(body))
+		//fmt.Println("GetEthTickbyPage1", req, string(body))
 		return offset, nil
 	}
 	total := len(dataticks)
@@ -167,6 +250,7 @@ func GetEthTickbyPage(instrumentId, offset int64, cb func(*Market)) (int64, erro
 			fmt.Println("toMac=", err)
 			continue
 		}
+		ti.InsId = instrumentId
 		offset = id
 		cb(ti)
 	}
@@ -174,6 +258,80 @@ func GetEthTickbyPage(instrumentId, offset int64, cb func(*Market)) (int64, erro
 	return offset, nil
 }
 
+/*
+func GetEthTickbyPage(instrumentId, offset int64, cb func(*Market)) (int64, error) {
+	symbol := inss[int(instrumentId)]
+	//url := "http://122.224.124.250:10115/tender/default/kline?symbol=" + symbol + "&offset=" + fmt.Sprintf("%d", offset) + "&limit=100"
+	//url := "http://10.0.1.5:45659/tender/default/kline?symbol=" + symbol + "&offset=" + fmt.Sprintf("%d", offset) + "&limit=100"
+	//response, err := http.Get(url)
+	//if err != nil {
+	//return offset, err
+	//}
+	params := make(map[string]interface{})
+	params["symbol"] = symbol
+	params["offset"] = offset
+	params["limit"] = 100
+	req := make(map[string]interface{})
+	req["jsonrpc"] = "2.0"
+	req["method"] = "kline"
+	req["id"] = 0
+	req["params"] = params
+	bytesData, err := json.Marshal(req)
+	if err != nil {
+		//fmt.Println("2", err)
+		return offset, err
+	}
+	reader := bytes.NewReader(bytesData)
+	url := "http://47.91.198.174:45656"
+	request, err := http.NewRequest("POST", url, reader)
+	if err != nil {
+		//fmt.Println("3", err)
+		return offset, err
+	}
+	request.Header.Set("Content-Type", "application/json;charset=UTF-8")
+	client := http.Client{}
+	response, err := client.Do(request)
+	if err != nil {
+		//fmt.Println("4", err)
+		return offset, err
+	}
+	defer response.Body.Close()
+	body, err := ioutil.ReadAll(response.Body)
+	if err != nil {
+		//fmt.Println("f2", url, err)
+		return offset, err
+	}
+	var data map[string]interface{}
+	err = json.Unmarshal(body, &data)
+	if err != nil {
+		//fmt.Println("f3", url, err)
+		return offset, err
+	}
+	//fmt.Println(url)
+	dataticks, ok := data["result"].([]interface{})
+	if !ok {
+		//fmt.Println("GetEthTickbyPage1", req, string(body))
+		return offset, nil
+	}
+	total := len(dataticks)
+	if total == 0 {
+		//log.Println("GetEthTickbyPage2", url, string(body))
+	}
+	//offset += int64(total)
+	for _, tmp := range dataticks {
+		ti, id, err := toEthMK(tmp.(map[string]interface{}))
+		if err != nil {
+			fmt.Println("toMac=", err)
+			continue
+		}
+		ti.InsId = instrumentId
+		offset = id
+		cb(ti)
+	}
+
+	return offset, nil
+}
+*/
 func GetBtcTickbyPage(offset int64, cb func(*Market)) (int64, error) {
 	url := "http://32.33.cn:9902/tender/default/kline?symbol=BTC&offset=" + fmt.Sprintf("%d", offset) + "&limit=100"
 	response, err := http.Get(url)
@@ -219,71 +377,6 @@ func GetBtcTickbyPage(offset int64, cb func(*Market)) (int64, error) {
 func toEthMK(data map[string]interface{}) (*Market, int64, error) {
 	mk := &Market{}
 	mk.Type = IntBty
-	symbolId := int32(data["symbolid"].(float64))
-	switch symbolId {
-	case 327681:
-		mk.InsId = markinfo.ETCCNY
-	case 131073:
-		mk.InsId = markinfo.BTCCNY
-	case 262145:
-		mk.InsId = markinfo.ETHCNY
-	case 458753:
-		mk.InsId = markinfo.SCCNY
-	case 524289:
-		mk.InsId = markinfo.ZECCNY
-	case 589825:
-		mk.InsId = markinfo.BTSCNY
-	case 655361:
-		mk.InsId = markinfo.LTCCNY
-	case 720897:
-		mk.InsId = markinfo.BCCCNY
-	case 851969:
-		mk.InsId = markinfo.NYCCCNY
-	case 917505:
-		mk.InsId = markinfo.WTCCNY
-	case 262146:
-		mk.InsId = markinfo.ETHBTC
-	case 327682:
-		mk.InsId = markinfo.ETCBTC
-	case 524290:
-		mk.InsId = markinfo.ZECBTC
-	case 655362:
-		mk.InsId = markinfo.LTCBTC
-	case 720898:
-		mk.InsId = markinfo.BCCBTC
-	case 262159:
-		mk.InsId = markinfo.ETHUSDT
-	case 327695:
-		mk.InsId = markinfo.ETCUSDT
-	case 524303:
-		mk.InsId = markinfo.ZECUSDT
-	case 655375:
-		mk.InsId = markinfo.LTCUSDT
-	case 720911:
-		mk.InsId = markinfo.BCCUSDT
-	case 131087:
-		mk.InsId = markinfo.BTCUSDT
-	case 196623:
-		mk.InsId = markinfo.BTYUSDT
-	case 589839:
-		mk.InsId = markinfo.BTSUSDT
-	case 458767:
-		mk.InsId = markinfo.SCUSDT
-	case 196610:
-		mk.InsId = markinfo.BTYBTC
-	case 589826:
-		mk.InsId = markinfo.BTSBTC
-	case 458754:
-		mk.InsId = markinfo.SCBTC
-	case 786447:
-		mk.InsId = markinfo.YCCUSDT
-	case 1048591:
-		mk.InsId = markinfo.BTCSUSDT
-	case 1114127:
-		mk.InsId = markinfo.DCRUSDT
-	default:
-		return nil, 0, errors.New("invalid symbolid")
-	}
 	mk.Timestamp = parseKTime(data["time"].(string))
 	price := data["price"].(float64)
 	volume, _ := data["quantity"].(float64)
@@ -305,9 +398,183 @@ func toEthMK(data map[string]interface{}) (*Market, int64, error) {
 	bid[1] = volume
 	mk.Asks = append(mk.Asks, ask)
 	mk.Bids = append(mk.Bids, bid)
+
 	return mk, id, nil
 }
 
+//func toEthMK(data map[string]interface{}) (*Market, int64, error) {
+//mk := &Market{}
+//mk.Type = IntBty
+/*symbolId := int32(data["symbolid"].(float64))
+switch symbolId {
+case 0x50001:
+	mk.InsId = markinfo.ETCCNY
+case 0x20001:
+	mk.InsId = markinfo.BTCCNY
+case 0x40001:
+	mk.InsId = markinfo.ETHCNY
+case 0x70001:
+	mk.InsId = markinfo.SCCNY
+case 0x80001:
+	mk.InsId = markinfo.ZECCNY
+case 0x90001:
+	mk.InsId = markinfo.BTSCNY
+case 0xA0001:
+	mk.InsId = markinfo.LTCCNY
+case 0xB0001:
+	mk.InsId = markinfo.BCCCNY
+case 0xD0001:
+	mk.InsId = markinfo.NYCCCNY
+case 0xE0001:
+	mk.InsId = markinfo.WTCCNY
+case 0x40002:
+	mk.InsId = markinfo.ETHBTC
+case 0x50002:
+	mk.InsId = markinfo.ETCBTC
+case 0x80002:
+	mk.InsId = markinfo.ZECBTC
+case 0xA0002:
+	mk.InsId = markinfo.LTCBTC
+case 0xB0002:
+	mk.InsId = markinfo.BCCBTC
+case 0x4000F:
+	mk.InsId = markinfo.ETHUSDT
+case 0x5000F:
+	mk.InsId = markinfo.ETCUSDT
+case 0x8000F:
+	mk.InsId = markinfo.ZECUSDT
+case 0xA000F:
+	mk.InsId = markinfo.LTCUSDT
+case 0xB000F:
+	mk.InsId = markinfo.BCCUSDT
+case 0x2000F:
+	mk.InsId = markinfo.BTCUSDT
+case 0x3000F:
+	mk.InsId = markinfo.BTYUSDT
+case 0x9000F:
+	mk.InsId = markinfo.BTSUSDT
+case 0x7000F:
+	mk.InsId = markinfo.SCUSDT
+case 0x30002:
+	mk.InsId = markinfo.BTYBTC
+case 0x90002:
+	mk.InsId = markinfo.BTSBTC
+case 0x70002:
+	mk.InsId = markinfo.SCBTC
+case 0xC000F:
+	mk.InsId = markinfo.YCCUSDT
+case 0x11000F:
+	mk.InsId = markinfo.DCRUSDT
+case 0x10000F:
+	mk.InsId = markinfo.BNTUSDT
+case 0x100002:
+	mk.InsId = markinfo.BNTBTC
+case 0x12000F:
+	mk.InsId = markinfo.SCTCUSDT
+case 0x120002:
+	mk.InsId = markinfo.SCTCBTC
+case 0xC0002:
+	mk.InsId = markinfo.YCCBTC
+case 0xC0004:
+	mk.InsId = markinfo.YCCETH
+case 0x15000F:
+	mk.InsId = markinfo.JBUSDT
+case 0x150002:
+	mk.InsId = markinfo.JBBTC
+case 0x150004:
+	mk.InsId = markinfo.JBETH
+case 0x16000F:
+	mk.InsId = markinfo.OPTCUSDT
+case 0x160002:
+	mk.InsId = markinfo.OPTCBTC
+case 0x160004:
+	mk.InsId = markinfo.OPTCETH
+case 0x20004:
+	mk.InsId = markinfo.BTCETH
+case 0xB0004:
+	mk.InsId = markinfo.BCCETH
+case 0x80004:
+	mk.InsId = markinfo.ZECETH
+case 0x50004:
+	mk.InsId = markinfo.ETCETH
+case 0xA0004:
+	mk.InsId = markinfo.LTCETH
+case 0x130014:
+	mk.InsId = markinfo.STILT
+case 0x17000F:
+	mk.InsId = markinfo.ITVBUSDT
+case 0x170002:
+	mk.InsId = markinfo.ITVBBTC
+case 0x170004:
+	mk.InsId = markinfo.ITVBETH
+case 0x30004:
+	mk.InsId = markinfo.BTYETH
+case 0x1A000F:
+	mk.InsId = markinfo.FHUSDT
+case 0x1B000F:
+	mk.InsId = markinfo.CWVUSDT
+case 0x1A0004:
+	mk.InsId = markinfo.FHETH
+case 0x1C0004:
+	mk.InsId = markinfo.TMCETH
+case 0x1D000F:
+	mk.InsId = markinfo.FANSUSDT
+case 0x1D0002:
+	mk.InsId = markinfo.FANSBTC
+case 0x1D0004:
+	mk.InsId = markinfo.FANSETH
+case 0x1F0020:
+	mk.InsId = markinfo.WTBWTC
+case 0x21000F:
+	mk.InsId = markinfo.CNSUSDT
+default:
+	return nil, 0, errors.New("invalid symbolid")
+}
+mk.Timestamp = parseKTime(data["time"].(string))
+price := data["price"].(float64)
+volume, _ := data["quantity"].(float64)
+id := int64(data["id"].(float64))
+price /= (10000 * 10000)
+volume /= 100000000
+mk.Close = price
+mk.Open = price
+mk.High = price
+mk.Low = price
+mk.AllAmount = volume
+mk.AllVolume = volume
+mk.LastPrice = price
+mk.LastVolume = volume
+var ask, bid PP
+ask[0] = price
+ask[1] = volume
+bid[0] = price
+bid[1] = volume
+mk.Asks = append(mk.Asks, ask)
+mk.Bids = append(mk.Bids, bid)*/
+//mk.Timestamp = int64(data["time"].(float64)) * 1000
+//price := data["price"].(float64)
+//volume, _ := data["amount"].(float64)
+//id := int64(data["id"].(float64))
+//price /= (10000 * 10000)
+//volume /= 100000000
+//mk.Close = price
+//mk.Open = price
+//mk.High = price
+//mk.Low = price
+//mk.AllAmount = volume
+//mk.AllVolume = volume
+//mk.LastPrice = price
+//mk.LastVolume = volume
+//var ask, bid PP
+//ask[0] = price
+//ask[1] = volume
+//bid[0] = price
+//bid[1] = volume
+//mk.Asks = append(mk.Asks, ask)
+//mk.Bids = append(mk.Bids, bid)
+//return mk, id, nil
+//}
+
 func parseKTime(timeStr string) int64 {
 	loc, _ := time.LoadLocation("Asia/Chongqing")
 	var year, month, day, hour, minute, second int

+ 243 - 0
server/tick/ds_oanda.go_

@@ -0,0 +1,243 @@
+// Copyright 2013-2014 Fuzamei tech Ltd. All rights reserved.
+
+package tick
+
+// 本文件实现oanda数据源的tick数据获取下载和保存
+
+import (
+	"errors"
+	"fmt"
+	"io/ioutil"
+	"log"
+	"net/http"
+	"regexp"
+	"strconv"
+	"strings"
+	"time"
+
+	"dev.33.cn/markinfo"
+	"dev.33.cn/server/market"
+)
+
+type oandaPairStatistics struct {
+	Date       time.Time
+	BuyPercent float64
+	Rates      float64
+	Symbol     string
+}
+
+var oanda_base = int(200)
+
+var oanda_prev = make(map[string]*oandaPairStatistics)
+
+//var fetchoandaurl = "http://fxtrade.oanda.com/lang/cns/analysis/open-position-ratios"
+var fetchoandaurl = "https://www.oanda.com/forex-trading/analysis/open-position-ratios"
+
+func getOandaStatistics(ch chan<- *oandaPairStatistics) (err error) {
+	html, err := httpDownload(fetchoandaurl)
+	if err != nil {
+		return err
+	}
+	regex := regexp.MustCompile("(?is)<ol[\\s]+class=\"position-ratio-list\"[^>]*>(.*?)<\\/ol>")
+	matches := regex.FindAllStringSubmatch(html, -1)
+	if len(matches) != 2 {
+		log.Println(html)
+		return errors.New("regex matche error.")
+	}
+	//货币对--BuyPercent--SellPercent
+	ratio_graph := get_span(matches[0][0])
+	//货币对--Rates
+	rates := get_span(matches[1][0])
+	//精确到微妙
+	t := match_time(html)
+	if len(ratio_graph)%3 == 0 && len(rates)%2 == 0 && len(ratio_graph)/3 == len(rates)/2 {
+		for i := 0; i < len(ratio_graph)/3; i++ {
+			ops := &oandaPairStatistics{}
+			ops.Symbol = strings.Replace(ratio_graph[3*i], "/", "", -1)
+			ops.BuyPercent, _ = strconv.ParseFloat(ratio_graph[3*i+1], 64)
+			ops.Rates, _ = strconv.ParseFloat(rates[2*i+1], 64)
+			ops.Date = time.Unix(t/1000, (t%1000)*(1e6))
+			sendOanda(ch, ops)
+		}
+	} else {
+		return errors.New("invalid data.")
+	}
+	return
+}
+
+func sendOanda(ch chan<- *oandaPairStatistics, data *oandaPairStatistics) {
+	if prev_data, ok := oanda_prev[data.Symbol]; ok {
+		if *prev_data == *data {
+			return
+		}
+	}
+	// log.Println("oa client", data)
+	oanda_prev[data.Symbol] = data
+	select {
+	case ch <- data:
+	default:
+	}
+}
+
+func httpDownload(url string) (string, error) {
+	body, err := http.Get(url)
+	if err != nil {
+		fmt.Println(err)
+		return "", err
+	}
+	defer body.Body.Close()
+	b, err := ioutil.ReadAll(body.Body)
+	if err != nil {
+		fmt.Println(err)
+		return "", err
+	}
+	return string(b), nil
+}
+
+var timeregex = regexp.MustCompile("(?is)<input.*?id=\"generation-timestamp\".*?value=\"(\\d+)\".*?>")
+
+func match_time(html string) int64 {
+	result := timeregex.FindAllStringSubmatch(html, -1)
+	var time int64
+	if len(result) == 1 && len(result[0]) == 2 {
+		time, _ = strconv.ParseInt(result[0][1], 10, 64)
+	}
+	return time
+}
+
+var spanregex = regexp.MustCompile("(?is)<span[^>]+>.*?</span>")
+
+func get_span(text string) []string {
+	result := spanregex.FindAllString(text, -1)
+	for i := 0; i < len(result); i++ {
+		result[i] = strings.Trim(strip_tags(result[i]), " \t\r\n%")
+	}
+	return result
+}
+
+var stripregex = regexp.MustCompile("(?is)<[^>]+>")
+
+func strip_tags(text string) string {
+	return stripregex.ReplaceAllString(text, "")
+}
+
+var oandaInss = []string{
+	"EURCHF",
+	"XAGUSD",
+	"EURGBP",
+	"USDJPY",
+	"USDCAD",
+	"AUDJPY",
+	"USDCHF",
+	"XAUUSD",
+	"EURJPY",
+	"EURUSD",
+	"GBPCHF",
+	"AUDUSD",
+	"EURAUD",
+	"NZDUSD",
+	"GBPJPY",
+	"GBPUSD",
+}
+
+// OandaDS 实现数据源dataSource接口的定义
+type OandaDS struct {
+	*DSBase
+	conf *DsConf
+	//insMap map[string]*market.Instrument
+}
+
+func init() {
+	drivers[Oanda] = newOandaDS
+}
+
+func newOandaDS(conf *DsConf) (DataSource, error) {
+	log.Println("newOandaDS")
+	ods := &OandaDS{
+		DSBase: NewDsBase(conf),
+		conf:   conf,
+		//insMap: oandaInsMap(),
+	}
+	ods.insMap = oandaInsMap()
+	return ods, nil
+}
+
+func (ods *OandaDS) Name() string {
+	return Oanda
+}
+
+//func (ods *OandaDS) SubIns() *event.Event {
+//return ods.insPublisher.Event()
+//}
+
+func (ods *OandaDS) onMarket(ps *oandaPairStatistics) {
+	//insId := market.OandaPrefix + ps.Symbol
+	insId, _ := markinfo.SymbolId(ps.Symbol)
+	_, ok := ods.insMap[int64(insId)]
+	if !ok {
+		log.Fatal("OandaDS.onMarket error: insId is NOT in insMap:", insId)
+	}
+	//mk := ins.GetMk()
+	mk := &Market{}
+	mk.Type = IntOanda
+	mk.InsId = int64(insId)
+	mk.Timestamp = ps.Date.Unix() * 1000
+	mk.LastPrice = 100 - ps.BuyPercent
+	mk.LastVolume = 1
+	//ins.SetMk(mk)
+	ods.Save(mk)
+}
+
+/*func (ods *OandaDS) runHour() {
+	ht := time.Tick(time.Hour)
+	for _ = range ht {
+		for _, ins := range ods.insMap {
+			ods.Save(ins.GetMk())
+		}
+	}
+}*/
+
+func (ods *OandaDS) Run() {
+	log.Println("OandaDS.run")
+	//for _, ins := range ods.insMap {
+	//ods.insPublisher.Publish(ins)
+	//}
+	// go ods.runHour()
+	//go ods.RunSave(4)
+	ch := make(chan *oandaPairStatistics, 1024)
+	go func() {
+		for {
+			ps := <-ch
+			ods.onMarket(ps)
+		}
+	}()
+	for {
+		var err error
+		for {
+			err = getOandaStatistics(ch)
+			if err != nil {
+				log.Println(err)
+			}
+			time.Sleep(3 * time.Second)
+		}
+	}
+}
+
+func oandaInsMap() map[int64]*Instrument {
+	insMap := make(map[int64]*Instrument)
+	for _, x := range oandaInss {
+		//id := market.OandaPrefix + x
+		id, _ := markinfo.SymbolId(x)
+		u, _ := markinfo.SymbolUint(x)
+		ins := &Instrument{
+			Id:        int64(id),
+			Name:      x,
+			ExId:      market.Oanda,
+			Type:      market.Forex,
+			PriceInc:  u,
+			StartTime: time.Now().Unix() * 1000,
+		}
+		insMap[int64(id)] = ins
+	}
+	return insMap
+}

+ 23 - 0
server/tick/ds_oanda_test.go_

@@ -0,0 +1,23 @@
+// Copyright 2013-2014 Fuzamei tech Ltd. All rights reserved.
+
+package tick
+
+import (
+	"log"
+	//"market"
+	"testing"
+)
+
+func TestOanda(t *testing.T) {
+	conf := &DsConf{}
+	ds, _ := newOandaDS(conf) //, err
+	//if err != nil {
+	//t.Fatal(err)
+	//}
+	go ds.Run()
+	chmk := ds.GetMarket()
+	for mk := range chmk {
+		log.Println(getTime(mk.Timestamp), mk.InsId)
+	}
+	log.Println("@@@@@@@:go here")
+}

+ 2 - 1
server/tick/general.go

@@ -21,6 +21,7 @@ import (
 	"tickserver/framework/event"
 	"tickserver/markinfo"
 	"tickserver/server/market"
+
 	"github.com/niniwzw/http2"
 )
 
@@ -135,8 +136,8 @@ func (gds *GeneralDS) load() {
 			}
 		}
 		tickfile := path.Join(dir, curname)
-		//log.Println(tickfile)
 		ticks, _ := market.ReadTickFile(tickfile)
+		//log.Println(tickfile, len(ticks))
 		for _, tick := range ticks {
 			var mk market.Market
 			mk.InsId = v.Id

+ 1 - 1
server/tick/history.go

@@ -192,7 +192,7 @@ func (cm *CandleMaker) parse() {
 	// 保存数据到文件
 	ticker := time.Tick(time.Second * 30)
 	for t := range ticker {
-		if t.Hour() == 0 && t.Minute() == 30 { // 8:30点时保存
+		if t.Hour() == 8 && t.Minute() == 30 { // 8:30点时保存
 			if len(cm.files) > 0 {
 				for len(cm.files) > 0 {
 					bHas := false