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:
hubble_dubble
2026-01-26 00:19:54 +01:00
commit 3667c678e4
41 changed files with 3556 additions and 0 deletions

View 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))
}