ds_easyforex.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. // Copyright 2013-2014 Fuzamei tech Ltd. All rights reserved.
  2. package tick
  3. // 本文件实现easyforex数据源的tick数据获取下载和保存
  4. import (
  5. "bytes"
  6. "encoding/json"
  7. "fmt"
  8. "io"
  9. "log"
  10. "net/http"
  11. "strconv"
  12. "strings"
  13. "time"
  14. "tickserver/markinfo"
  15. "tickserver/server/market"
  16. "github.com/ble/cookiejar"
  17. )
  18. var pair = []string{
  19. "EURUSD",
  20. "EURGBP",
  21. "GBPUSD",
  22. "USDJPY",
  23. "USDCHF",
  24. "AUDUSD",
  25. "USDCAD",
  26. "NZDUSD",
  27. "CHFJPY",
  28. "EURJPY",
  29. "EURCHF",
  30. "EURAUD",
  31. "EURCAD",
  32. "GBPCHF",
  33. "GBPJPY",
  34. "CADJPY",
  35. "AUDJPY",
  36. "AUDCAD",
  37. "AUDNZD",
  38. "XAGUSD",
  39. "XAUUSD",
  40. "OILUSD",
  41. }
  42. var easyforex_base = int(100)
  43. func logOn(client *http.Client, username, password string) error {
  44. loginUrl := "https://secure.easy-forex.com/ntp/myaccount/services/loginservice.ashx?action=AuthenticateUser"
  45. loginUrl = loginUrl + "&username=%s&password=%s&pid=42&culture=Int-en&simulator=false"
  46. login := fmt.Sprintf(loginUrl, username, password)
  47. resp, err := client.Get(login)
  48. if err != nil {
  49. return err
  50. }
  51. defer resp.Body.Close()
  52. dec := json.NewDecoder(resp.Body)
  53. data := make(map[string]interface{})
  54. err = dec.Decode(&data)
  55. if err != nil {
  56. return err
  57. }
  58. if data["encData"] == nil {
  59. return fmt.Errorf("error login format.")
  60. }
  61. doLoginUrl := "https://secure.easy-forex.com/ntp/myaccount/services/loginservice.ashx?action=DoLogin&pid=42&encData=%s&culture=Int-en&isSimulator=&service=0"
  62. doLogin := fmt.Sprintf(doLoginUrl, data["encData"].(string))
  63. resp2, err := client.Get(doLogin)
  64. if err != nil {
  65. return err
  66. }
  67. defer resp2.Body.Close()
  68. dec = json.NewDecoder(resp2.Body)
  69. data2 := make(map[string]interface{})
  70. err = dec.Decode(&data2)
  71. if err != nil {
  72. return err
  73. }
  74. return nil
  75. }
  76. type PairStatistics struct {
  77. Date time.Time
  78. BuyPercent float64
  79. Rates float64
  80. Symbol string
  81. }
  82. func getStatistics(client *http.Client, symbol string) (stat *PairStatistics, err error) {
  83. defer func() {
  84. if err2 := recover(); err2 != nil {
  85. err = fmt.Errorf("%v", err2)
  86. }
  87. }()
  88. r := []rune(symbol)
  89. s1 := string(r[:3])
  90. s2 := string(r[3:])
  91. url := "https://secure.easy-forex.com/ntp/Machine/TradingZone/tz.ashx?RQ=[{%22action%22%3A%22GetCurrencyPairStatistics%22%2C%22args%22%3A"
  92. url += "{%22buy%22%3A%22" + s1 + "%22%2C%22sell%22%3A%22" + s2 + "%22}}"
  93. url += "%2C{%22action%22%3A%22GetTableMids%22%2C%22args%22%3A{%22isExpanded%22%3A0%2C%22productId%22%3A3}}"
  94. url += "%2C{%22action%22%3A%22GetDtrProposal%22%2C%22args%22%3A[null%2C%22USD%22%2C%22AUD%22%2C4%2C100%2C3]}"
  95. url += "%2C{%22action%22%3A%22GetFreeBalance%22}]&MODE=isCurrencies&Heartbeat=0"
  96. resp, err := client.Get(url)
  97. if err != nil {
  98. return nil, err
  99. }
  100. defer resp.Body.Close()
  101. buf := bytes.NewBufferString("")
  102. _, err = io.Copy(buf, resp.Body)
  103. if err != nil {
  104. return nil, err
  105. }
  106. var data []map[string]interface{}
  107. s := buf.String()
  108. s = strings.Replace(s, "GetCurrencyPairStatistics", `"GetCurrencyPairStatistics"`, 1)
  109. s = strings.Replace(s, "GetTableMids", `"GetTableMids"`, 1)
  110. s = strings.Replace(s, "GetDtrProposal", `"GetDtrProposal"`, 1)
  111. s = strings.Replace(s, "GetFreeBalance", `"GetFreeBalance"`, 1)
  112. err = json.Unmarshal([]byte(s), &data)
  113. if err != nil {
  114. return nil, err
  115. }
  116. pstat := data[0]["GetCurrencyPairStatistics"].(map[string]interface{})
  117. if _, ok := pstat["error"]; ok {
  118. // log.Println("GetCurrencyPairStatistics code = ", pstat["error"], symbol)
  119. return nil, nil
  120. }
  121. currentRate := pstat["currentRate"].(string)
  122. buyPercent := pstat["BuyPercent"].(float64)
  123. curRateDate := data[0]["GetDtrProposal"].([]interface{})[3].(map[string]interface{})["curRateDate"].(string)
  124. gotime, err := parseTime(curRateDate)
  125. if err != nil {
  126. return nil, err
  127. }
  128. _, err = markinfo.SymbolId(symbol)
  129. if err != nil {
  130. return nil, err
  131. }
  132. stat = &PairStatistics{}
  133. stat.Date = gotime
  134. stat.BuyPercent = buyPercent
  135. stat.Rates, err = strconv.ParseFloat(currentRate, 64)
  136. if err != nil {
  137. return nil, err
  138. }
  139. stat.Symbol = symbol
  140. return stat, err
  141. }
  142. func parseTime(curRateDate string) (time.Time, error) {
  143. //curRateDate to time
  144. //23/01/13 10:48:25.140
  145. curRateDate = strings.Replace(curRateDate, "/", " ", -1)
  146. curRateDate = strings.Replace(curRateDate, ":", " ", -1)
  147. curRateDate = strings.Replace(curRateDate, ".", " ", -1)
  148. parts := strings.Split(curRateDate, " ")
  149. dates := make([]int, len(parts))
  150. for i := 0; i < len(dates); i++ {
  151. value, err := strconv.Atoi(parts[i])
  152. if err != nil {
  153. return time.Time{}, err
  154. }
  155. dates[i] = value
  156. }
  157. 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)
  158. return godate, nil
  159. }
  160. // EasyForexDS 实现数据源dataSource接口的定义
  161. type EasyForexDS struct {
  162. *DSBase
  163. conf *DsConf
  164. //insMap map[string]*market.Instrument
  165. }
  166. func init() {
  167. drivers[EasyForex] = newEasyForexDS
  168. }
  169. func newEasyForexDS(conf *DsConf) (DataSource, error) {
  170. eds := &EasyForexDS{
  171. DSBase: NewDsBase(conf),
  172. conf: conf,
  173. //insMap: edsInsMap(),
  174. }
  175. eds.insMap = edsInsMap()
  176. return eds, nil
  177. }
  178. func (eds *EasyForexDS) onMarket(ps *PairStatistics) {
  179. //insId := market.EasyForexPrefix + ps.Symbol
  180. insId, _ := markinfo.SymbolId(ps.Symbol)
  181. _, ok := eds.insMap[int64(insId)]
  182. if !ok {
  183. log.Fatal("EasyForexDS.onMarket error: insId is NOT in insMap:", insId)
  184. }
  185. //mk := ins.GetMk()
  186. mk := &Market{}
  187. mk.InsId = int64(insId)
  188. mk.Type = IntEasyForex
  189. mk.Timestamp = ps.Date.Unix() * 1000
  190. mk.LastPrice = 100 - ps.BuyPercent
  191. mk.LastVolume = 1
  192. //ins.SetMk(mk)
  193. eds.Save(mk)
  194. }
  195. /*func (eds *EasyForexDS) runHour() {
  196. ht := time.Tick(time.Hour)
  197. for _ = range ht {
  198. for _, ins := range eds.insMap {
  199. eds.Save(ins.GetMk())
  200. }
  201. }
  202. }*/
  203. func (eds *EasyForexDS) Name() string {
  204. return EasyForex
  205. }
  206. func (eds *EasyForexDS) Run() {
  207. log.Println("EasyForexDS.run")
  208. //for _, ins := range eds.insMap {
  209. //eds.insPublisher.Publish(ins)
  210. //}
  211. // go eds.runHour()
  212. //go eds.RunSave(4)
  213. ch := make(chan *PairStatistics, 1024)
  214. go func() {
  215. for {
  216. ps := <-ch
  217. eds.onMarket(ps)
  218. }
  219. }()
  220. for {
  221. client := &http.Client{Jar: cookiejar.NewJar(false)}
  222. err := logOn(client, "Ty2388", "4536888")
  223. var stat *PairStatistics
  224. var laststat = make(map[string]*PairStatistics)
  225. if err != nil {
  226. log.Println(err)
  227. goto END
  228. }
  229. for {
  230. for i := 0; i < len(pair); i++ {
  231. stat, err = getStatistics(client, pair[i])
  232. if err != nil {
  233. goto END
  234. }
  235. if stat != nil {
  236. if _, ok := laststat[stat.Symbol]; !ok {
  237. ch <- stat
  238. laststat[stat.Symbol] = stat
  239. } else if *laststat[stat.Symbol] != *stat && laststat[stat.Symbol].Date.Sub(stat.Date) < 0 {
  240. ch <- stat
  241. laststat[stat.Symbol] = stat
  242. }
  243. }
  244. }
  245. }
  246. END:
  247. log.Println(err)
  248. time.Sleep(time.Second)
  249. }
  250. }
  251. //func (eds *EasyForexDS) SubIns() *event.Event {
  252. //return eds.insPublisher.Event()
  253. //}
  254. func edsInsMap() map[int64]*Instrument {
  255. insMap := make(map[int64]*Instrument)
  256. for _, x := range pair {
  257. //id := market.EasyForexPrefix + x
  258. id, _ := markinfo.SymbolId(x)
  259. u, _ := markinfo.SymbolUint(x)
  260. ins := &Instrument{
  261. Id: int64(id),
  262. Name: x,
  263. ExId: market.EasyForex,
  264. Type: market.Forex,
  265. PriceInc: u,
  266. StartTime: time.Now().Unix() * 1000,
  267. }
  268. insMap[int64(id)] = ins
  269. }
  270. return insMap
  271. }