Please enter the commit message for your changes. Lines starting
with '#' will be ignored, and an empty message aborts the commit. On branch main Initial commit Changes to be committed: new file: .DS_Store new file: .env new file: .gitignore new file: ai-worker/Dockerfile new file: ai-worker/requirements.txt new file: ai-worker/worker.py new file: background-worker/Dockerfile new file: background-worker/go.mod new file: background-worker/go.sum new file: background-worker/main.go new file: background-worker/market.go new file: background-worker/rmv.go new file: background-worker/rss.go new file: background-worker/sql_work.go new file: db/Dockerfile new file: db/init.sql new file: docker-compose.yml new file: server-app/dockerfile new file: server-app/go.mod new file: server-app/go.sum new file: server-app/main.go new file: volumes/.DS_Store new file: volumes/db-init/.DS_Store new file: volumes/db-init/data/news_rss_feeds.csv new file: volumes/web/.DS_Store new file: volumes/web/static/css/blog.css new file: volumes/web/static/css/index-lite.css new file: volumes/web/static/css/index.css new file: volumes/web/static/css/mandelbrot.css new file: volumes/web/static/img/minecraft.png new file: volumes/web/static/js/blog.js new file: volumes/web/static/js/index-lite.js new file: volumes/web/static/js/index.js new file: volumes/web/static/js/mandelbrot.js new file: volumes/web/static/media/cantina.mp3 new file: volumes/web/static/media/countdowns.json new file: volumes/web/static/media/gong.mp4 new file: volumes/web/template/blog.html new file: volumes/web/template/index-lite.html new file: volumes/web/template/index.html new file: volumes/web/template/mandelbrot.html
This commit is contained in:
87
background-worker/market.go
Normal file
87
background-worker/market.go
Normal file
@@ -0,0 +1,87 @@
|
||||
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))
|
||||
}
|
||||
Reference in New Issue
Block a user