package main import ( "context" "encoding/json" "log" "net/http" "time" ) type marketQuote struct { Instrument string Bid float64 QuotedAt time.Time } type sqResponse struct { SpreadProfilePrices []struct { Bid float64 `json:"bid"` } `json:"spreadProfilePrices"` Timestamp int64 `json:"timestamp"` } func fetchMarketData() { ctx := context.Background() client := http.Client{Timeout: 10 * time.Second} type endpoint struct { Instrument string URL string } endpoints := []endpoint{ {Instrument: "USD/JPY", URL: "https://forex-data-feed.swissquote.com/public-quotes/bboquotes/instrument/USD/JPY"}, {Instrument: "OIL/USD", URL: "https://forex-data-feed.swissquote.com/public-quotes/bboquotes/instrument/OIL/USD"}, {Instrument: "XAU/USD", URL: "https://forex-data-feed.swissquote.com/public-quotes/bboquotes/instrument/XAU/USD"}, {Instrument: "EUR/USD", URL: "https://forex-data-feed.swissquote.com/public-quotes/bboquotes/instrument/EUR/USD"}, {Instrument: "USD/CHF", URL: "https://forex-data-feed.swissquote.com/public-quotes/bboquotes/instrument/USD/CHF"}, {Instrument: "GBP/USD", URL: "https://forex-data-feed.swissquote.com/public-quotes/bboquotes/instrument/GBP/USD"}, } var quotes []MarketQuote for _, ep := range endpoints { req, _ := http.NewRequestWithContext(ctx, http.MethodGet, ep.URL, nil) resp, err := client.Do(req) if err != nil { log.Printf("market fetch %s failed: %v", ep.Instrument, err) continue } if resp.StatusCode != http.StatusOK { resp.Body.Close() log.Printf("market fetch %s bad status: %s", ep.Instrument, resp.Status) continue } var payload []sqResponse if err := json.NewDecoder(resp.Body).Decode(&payload); err != nil { resp.Body.Close() log.Printf("decode %s failed: %v", ep.Instrument, err) continue } resp.Body.Close() if len(payload) == 0 || len(payload[0].SpreadProfilePrices) == 0 { log.Printf("market fetch %s: empty payload", ep.Instrument) continue } bid := payload[0].SpreadProfilePrices[0].Bid quotedAt := time.UnixMilli(payload[0].Timestamp) quotes = append(quotes, MarketQuote{ Instrument: ep.Instrument, Bid: bid, QuotedAt: quotedAt, }) } if len(quotes) == 0 { return } if err := saveMarketQuotes(ctx, quotes); err != nil { log.Printf("saveMarketQuotes failed: %v", err) } log.Printf("market quotes updated: %d instruments", len(quotes)) }