123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- // Copyright 2013-2014 Fuzamei tech Ltd. All rights reserved.
- package tick
- // 本文件实现easyforex数据源的tick数据获取下载和保存
- import (
- "bytes"
- "encoding/json"
- "fmt"
- "io"
- "log"
- "net/http"
- "strconv"
- "strings"
- "time"
- "tickserver/markinfo"
- "tickserver/server/market"
- "github.com/ble/cookiejar"
- )
- var pair = []string{
- "EURUSD",
- "EURGBP",
- "GBPUSD",
- "USDJPY",
- "USDCHF",
- "AUDUSD",
- "USDCAD",
- "NZDUSD",
- "CHFJPY",
- "EURJPY",
- "EURCHF",
- "EURAUD",
- "EURCAD",
- "GBPCHF",
- "GBPJPY",
- "CADJPY",
- "AUDJPY",
- "AUDCAD",
- "AUDNZD",
- "XAGUSD",
- "XAUUSD",
- "OILUSD",
- }
- var easyforex_base = int(100)
- func logOn(client *http.Client, username, password string) error {
- loginUrl := "https://secure.easy-forex.com/ntp/myaccount/services/loginservice.ashx?action=AuthenticateUser"
- loginUrl = loginUrl + "&username=%s&password=%s&pid=42&culture=Int-en&simulator=false"
- login := fmt.Sprintf(loginUrl, username, password)
- resp, err := client.Get(login)
- if err != nil {
- return err
- }
- defer resp.Body.Close()
- dec := json.NewDecoder(resp.Body)
- data := make(map[string]interface{})
- err = dec.Decode(&data)
- if err != nil {
- return err
- }
- if data["encData"] == nil {
- return fmt.Errorf("error login format.")
- }
- doLoginUrl := "https://secure.easy-forex.com/ntp/myaccount/services/loginservice.ashx?action=DoLogin&pid=42&encData=%s&culture=Int-en&isSimulator=&service=0"
- doLogin := fmt.Sprintf(doLoginUrl, data["encData"].(string))
- resp2, err := client.Get(doLogin)
- if err != nil {
- return err
- }
- defer resp2.Body.Close()
- dec = json.NewDecoder(resp2.Body)
- data2 := make(map[string]interface{})
- err = dec.Decode(&data2)
- if err != nil {
- return err
- }
- return nil
- }
- type PairStatistics struct {
- Date time.Time
- BuyPercent float64
- Rates float64
- Symbol string
- }
- func getStatistics(client *http.Client, symbol string) (stat *PairStatistics, err error) {
- defer func() {
- if err2 := recover(); err2 != nil {
- err = fmt.Errorf("%v", err2)
- }
- }()
- r := []rune(symbol)
- s1 := string(r[:3])
- s2 := string(r[3:])
- url := "https://secure.easy-forex.com/ntp/Machine/TradingZone/tz.ashx?RQ=[{%22action%22%3A%22GetCurrencyPairStatistics%22%2C%22args%22%3A"
- url += "{%22buy%22%3A%22" + s1 + "%22%2C%22sell%22%3A%22" + s2 + "%22}}"
- url += "%2C{%22action%22%3A%22GetTableMids%22%2C%22args%22%3A{%22isExpanded%22%3A0%2C%22productId%22%3A3}}"
- url += "%2C{%22action%22%3A%22GetDtrProposal%22%2C%22args%22%3A[null%2C%22USD%22%2C%22AUD%22%2C4%2C100%2C3]}"
- url += "%2C{%22action%22%3A%22GetFreeBalance%22}]&MODE=isCurrencies&Heartbeat=0"
- resp, err := client.Get(url)
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
- buf := bytes.NewBufferString("")
- _, err = io.Copy(buf, resp.Body)
- if err != nil {
- return nil, err
- }
- var data []map[string]interface{}
- s := buf.String()
- s = strings.Replace(s, "GetCurrencyPairStatistics", `"GetCurrencyPairStatistics"`, 1)
- s = strings.Replace(s, "GetTableMids", `"GetTableMids"`, 1)
- s = strings.Replace(s, "GetDtrProposal", `"GetDtrProposal"`, 1)
- s = strings.Replace(s, "GetFreeBalance", `"GetFreeBalance"`, 1)
- err = json.Unmarshal([]byte(s), &data)
- if err != nil {
- return nil, err
- }
- pstat := data[0]["GetCurrencyPairStatistics"].(map[string]interface{})
- if _, ok := pstat["error"]; ok {
- // log.Println("GetCurrencyPairStatistics code = ", pstat["error"], symbol)
- return nil, nil
- }
- currentRate := pstat["currentRate"].(string)
- buyPercent := pstat["BuyPercent"].(float64)
- curRateDate := data[0]["GetDtrProposal"].([]interface{})[3].(map[string]interface{})["curRateDate"].(string)
- gotime, err := parseTime(curRateDate)
- if err != nil {
- return nil, err
- }
- _, err = markinfo.SymbolId(symbol)
- if err != nil {
- return nil, err
- }
- stat = &PairStatistics{}
- stat.Date = gotime
- stat.BuyPercent = buyPercent
- stat.Rates, err = strconv.ParseFloat(currentRate, 64)
- if err != nil {
- return nil, err
- }
- stat.Symbol = symbol
- return stat, err
- }
- func parseTime(curRateDate string) (time.Time, error) {
- //curRateDate to time
- //23/01/13 10:48:25.140
- curRateDate = strings.Replace(curRateDate, "/", " ", -1)
- curRateDate = strings.Replace(curRateDate, ":", " ", -1)
- curRateDate = strings.Replace(curRateDate, ".", " ", -1)
- parts := strings.Split(curRateDate, " ")
- dates := make([]int, len(parts))
- for i := 0; i < len(dates); i++ {
- value, err := strconv.Atoi(parts[i])
- if err != nil {
- return time.Time{}, err
- }
- dates[i] = value
- }
- godate := time.Date(2000+dates[2], time.Month(dates[1]), dates[0], dates[3], dates[4], dates[5], dates[6]*int(time.Millisecond), time.UTC)
- return godate, nil
- }
- // EasyForexDS 实现数据源dataSource接口的定义
- type EasyForexDS struct {
- *DSBase
- conf *DsConf
- //insMap map[string]*market.Instrument
- }
- func init() {
- drivers[EasyForex] = newEasyForexDS
- }
- func newEasyForexDS(conf *DsConf) (DataSource, error) {
- eds := &EasyForexDS{
- DSBase: NewDsBase(conf),
- conf: conf,
- //insMap: edsInsMap(),
- }
- eds.insMap = edsInsMap()
- return eds, nil
- }
- func (eds *EasyForexDS) onMarket(ps *PairStatistics) {
- //insId := market.EasyForexPrefix + ps.Symbol
- insId, _ := markinfo.SymbolId(ps.Symbol)
- _, ok := eds.insMap[int64(insId)]
- if !ok {
- log.Fatal("EasyForexDS.onMarket error: insId is NOT in insMap:", insId)
- }
- //mk := ins.GetMk()
- mk := &Market{}
- mk.InsId = int64(insId)
- mk.Type = IntEasyForex
- mk.Timestamp = ps.Date.Unix() * 1000
- mk.LastPrice = 100 - ps.BuyPercent
- mk.LastVolume = 1
- //ins.SetMk(mk)
- eds.Save(mk)
- }
- /*func (eds *EasyForexDS) runHour() {
- ht := time.Tick(time.Hour)
- for _ = range ht {
- for _, ins := range eds.insMap {
- eds.Save(ins.GetMk())
- }
- }
- }*/
- func (eds *EasyForexDS) Name() string {
- return EasyForex
- }
- func (eds *EasyForexDS) Run() {
- log.Println("EasyForexDS.run")
- //for _, ins := range eds.insMap {
- //eds.insPublisher.Publish(ins)
- //}
- // go eds.runHour()
- //go eds.RunSave(4)
- ch := make(chan *PairStatistics, 1024)
- go func() {
- for {
- ps := <-ch
- eds.onMarket(ps)
- }
- }()
- for {
- client := &http.Client{Jar: cookiejar.NewJar(false)}
- err := logOn(client, "Ty2388", "4536888")
- var stat *PairStatistics
- var laststat = make(map[string]*PairStatistics)
- if err != nil {
- log.Println(err)
- goto END
- }
- for {
- for i := 0; i < len(pair); i++ {
- stat, err = getStatistics(client, pair[i])
- if err != nil {
- goto END
- }
- if stat != nil {
- if _, ok := laststat[stat.Symbol]; !ok {
- ch <- stat
- laststat[stat.Symbol] = stat
- } else if *laststat[stat.Symbol] != *stat && laststat[stat.Symbol].Date.Sub(stat.Date) < 0 {
- ch <- stat
- laststat[stat.Symbol] = stat
- }
- }
- }
- }
- END:
- log.Println(err)
- time.Sleep(time.Second)
- }
- }
- //func (eds *EasyForexDS) SubIns() *event.Event {
- //return eds.insPublisher.Event()
- //}
- func edsInsMap() map[int64]*Instrument {
- insMap := make(map[int64]*Instrument)
- for _, x := range pair {
- //id := market.EasyForexPrefix + x
- id, _ := markinfo.SymbolId(x)
- u, _ := markinfo.SymbolUint(x)
- ins := &Instrument{
- Id: int64(id),
- Name: x,
- ExId: market.EasyForex,
- Type: market.Forex,
- PriceInc: u,
- StartTime: time.Now().Unix() * 1000,
- }
- insMap[int64(id)] = ins
- }
- return insMap
- }
|