// +build linux // Copyright 2013-2014 Fuzamei tech Ltd. All rights reserved. package tick // 本文件实现方正FIX数据源接口, 实时数据和历史数据的获取和保存 import ( "encoding/json" "errors" "io/ioutil" "log" "os" "strconv" "strings" "tickserver/api/gofix" ) type StockInfo struct { Id string Name string ExId string PriceInc float64 Margin float64 StartTime string } // FixDS实现了dataSource接口, 并对fix的历史数据和实时数据保存 type FixDS struct { *DSBase conf *DsConf fixCfgFile string symbolMap map[string]string insMap map[int64]*StockInfo } func init() { drivers[Fix] = newFixDS } func newFixDS(conf *DsConf) (DataSource, error) { m := make(map[string]*StockInfo) f, err := os.Open(conf.SymbolsFile) if err != nil { si := &StockInfo{ Id: "600000", ExId: "XSHG", Name: "浦发银行", PriceInc: 0.01, StartTime: "1999-11-10", } m[si.Id] = si b, _ := json.MarshalIndent(&m, "", " ") ioutil.WriteFile(conf.SymbolsFile, b, os.ModePerm) return nil, err } dec := json.NewDecoder(f) err = dec.Decode(&m) if err != nil { return nil, err } symbolMap := make(map[string]string) insMap := make(map[int64]*StockInfo) for k, v := range m { symbolMap[k] = v.ExId insId, _ := strconv.ParseInt(k, 10, 64) //insId := market.FixPrefix + k ss := strings.Split(v.StartTime, "-") if len(ss) != 3 { return nil, errors.New("StartTime format is Illegal. MUST yyyy-mm-dd format") } _, err := strconv.Atoi(ss[0]) if err != nil { return nil, errors.New("StartTime format error:" + err.Error()) } _, err = strconv.Atoi(ss[1]) if err != nil { return nil, errors.New("StartTime format error:" + err.Error()) } _, err = strconv.Atoi(ss[2]) if err != nil { return nil, errors.New("StartTime format error:" + err.Error()) } //t := time.Date(y, time.Month(m), d, 0, 0, 0, 0, time.Local) /*ins := &market.Instrument{ Id: insId, Name: v.Name, Typ: market.Securities, ExId: v.ExId, PriceInc: v.PriceInc, Margin: v.Margin, StartTime: t.Unix() * 1000, }*/ //insMap[insId] = ins insMap[insId] = v } return &FixDS{ DSBase: NewDsBase(conf), conf: conf, symbolMap: symbolMap, insMap: insMap, }, nil } //func (fds *FixDS) SubIns() *event.Event { //return fds.insPublisher.Event() //} // func (fds *FixDS) GetInsMap() map[string]*market.Instrument { // return fds.insMap // } // func (fds *FixDS) GetInsName(insId string) string { // return fds.insMap[insId].Name // } func (fds *FixDS) Name() string { return Fix } func (fds *FixDS) Run() { log.Println("FixDS.Run") //for _, ins := range fds.insMap { //fds.insPublisher.Publish(ins) //} fixApp := gofix.NewApp(fds.symbolMap, fds.conf.User, fds.conf.PassWord) go fixApp.Run(fds.conf.CfgFile) //go fds.RunSave(16) log.Printf("%+v\n", fds.insMap) for fixTick := range fixApp.Ch { m := convMarket(fixTick) _, ok := fds.insMap[m.InsId] if !ok { for k, _ := range fds.insMap { log.Println(k, m.InsId, k == m.InsId) //, []byte(k), []byte(m.InsId) } log.Println("error: the market data NOT in insMap:", m.InsId, fds.insMap) continue } //if m.Timestamp < ins.StartTime { //log.Println("error: m.Timestamp < ins.StartTime:", m.Timestamp, ins.StartTime) //continue //} // log.Println(market.GetTime(m.Timestamp)) // fds.marketPublisher.Publish(m) //ins.SetMk(m) fds.Save(m) } } func convMarket(tick *gofix.FixTick) *Market { //insId := market.FixPrefix + gofix.Symbol(tick.Symbol) insId, _ := strconv.ParseInt(string(tick.Symbol[:]), 10, 64) asks := make([]PP, tick.AskCount) bids := make([]PP, tick.BidCount) for i := 0; i < int(tick.AskCount); i++ { asks[i][0] = tick.AskPrice[i] asks[i][1] = float64(tick.AskVolume[i]) } for i := 0; i < int(tick.AskCount); i++ { bids[i][0] = tick.BidPrice[i] bids[i][1] = float64(tick.BidVolume[i]) } return &Market{ InsId: insId, Type: IntFix, Timestamp: int64(tick.Time)*1000 + int64(tick.Millisecond), Bids: bids, Asks: asks, } }