package mainimport ( "encoding/json" "fmt" "io/ioutil" "net/http" "net/url" "sort" "strconv" "strings" "time" "github.com/davecgh/go-spew/spew")const defProxy = "https://usr:psswd@192.168.1.148:8080"var ( KnownSymbols = []string{ "BTC", "ETH", "USDT", "ETC", })func findSuffix(pairname string) string { for _, suf := range KnownSymbols { if strings.HasSuffix(pairname, suf) { return suf } } return ""}func splitPair(pairname string) (string, string) { s := findSuffix(pairname) return pairname[:len(s)], pairname[len(pairname)-len(s):]}var ( ExcludedSymbols = []string{ "123456", })func isExcludedSymbol(name string) bool { for _, v := range ExcludedSymbols { if v == name { return true } } return false}type BaItem struct { Symbol string `json:"symbol"` Price string `json:"price"` Numerator string Denominator string Rate float64}type baItem BaItemfunc (b *BaItem) UnmarshalJSON(bytes []byte) (err error) { j := baItem{} err = json.Unmarshal(bytes, &j) if err == nil { *b = BaItem(j) b.Numerator, b.Denominator = splitPair(b.Symbol) b.Rate, _ = strconv.ParseFloat(b.Price, 64) } return}func (b *BaItem) String() string { return fmt.Sprintf("%v=>%v:%f", b.Numerator, b.Denominator, b.Rate)}type TSnapshot []BaItemtype BaAgent struct { client *http.Client}type TsEntry struct { Timestamp time.Time Tsa TSnapshot}func newConn() *http.Client { tr := &http.Transport{ MaxIdleConns: 10, IdleConnTimeout: 10 * time.Second, DisableCompression: true, DisableKeepAlives: false, } url, eUrl := url.Parse(defProxy) if eUrl != nil { panic(eUrl) } tr.Proxy = http.ProxyURL(url) return &http.Client{ Transport: tr, }}func NewBaAgent() *BaAgent { return &BaAgent{ client: newConn(), }}func (b *BaAgent) GetSnapshot() (*TsEntry, error) { const ticker_uri = "https://www.binance.com/api/v1/ticker/allPrices" resp, err := b.client.Get(ticker_uri) if err != nil { return nil, err } defer resp.Body.Close() chunk, eChunk := ioutil.ReadAll(resp.Body) if eChunk != nil { return nil, eChunk } var tsa TSnapshot if e := json.Unmarshal(chunk, &tsa); e != nil { return nil, e } return &TsEntry{ Timestamp: time.Now(), Tsa: tsa, }, nil}type ExchangeItem struct { Name string EthBtcPair float64}type ExchangeItemArr []ExchangeItemfunc (s ExchangeItemArr) Len() int { return len(s)}func (s ExchangeItemArr) Swap(i, j int) { s[i], s[j] = s[j], s[i]}func (s ExchangeItemArr) Less(i, j int) bool { return s[i].EthBtcPair < s[j].EthBtcPair}func Traverse(snap TsEntry) { fmt.Printf("start analyzing %v\n", snap.Timestamp.Format(time.RFC822)) fromMap := make(map[string]map[string]float64) for _, ent := range snap.Tsa { if nil == fromMap[ent.Numerator] { fromMap[ent.Numerator] = make(map[string]float64) } fromMap[ent.Numerator][ent.Denominator] = ent.Rate } spew.Dump(fromMap) var exi []ExchangeItem stdR := fromMap["ETH"]["BTC"] for kind, ent := range fromMap { b_rate, btcOK := ent["BTC"] e_rate, ethOK := ent["ETH"] if btcOK && ethOK { esteR := 1 / e_rate * b_rate exi = append(exi, ExchangeItem{kind, esteR / stdR}) } } sort.Sort(ExchangeItemArr(exi)) fmt.Println("******************************") spew.Dump(exi)}func main() { ba := NewBaAgent() if snap, e := ba.GetSnapshot(); nil == e { for _, snap := range snap.Tsa { if isExcludedSymbol(snap.Symbol) { continue } found := false for _, n := range KnownSymbols { if strings.HasSuffix(snap.Symbol, n) { found = true break } } if !found { fmt.Printf("Unknown symbol: %v\n", snap.Symbol) } } fmt.Println() Traverse(*snap) } else { fmt.Printf("Error: %v\n", e) } }