├── go.mod ├── go.sum ├── server.go ├── stocks.go └── views ├── index.html ├── results.html └── values.html /go.mod: -------------------------------------------------------------------------------- 1 | module app 2 | 3 | go 1.20 4 | 5 | require ( 6 | github.com/andybalholm/brotli v1.0.5 // indirect 7 | github.com/gofiber/fiber/v2 v2.48.0 // indirect 8 | github.com/gofiber/template v1.8.2 // indirect 9 | github.com/gofiber/template/html/v2 v2.0.5 // indirect 10 | github.com/gofiber/utils v1.1.0 // indirect 11 | github.com/google/uuid v1.3.0 // indirect 12 | github.com/klauspost/compress v1.16.3 // indirect 13 | github.com/mattn/go-colorable v0.1.13 // indirect 14 | github.com/mattn/go-isatty v0.0.19 // indirect 15 | github.com/mattn/go-runewidth v0.0.14 // indirect 16 | github.com/rivo/uniseg v0.2.0 // indirect 17 | github.com/valyala/bytebufferpool v1.0.0 // indirect 18 | github.com/valyala/fasthttp v1.48.0 // indirect 19 | github.com/valyala/tcplisten v1.0.0 // indirect 20 | golang.org/x/sys v0.10.0 // indirect 21 | ) 22 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= 2 | github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= 3 | github.com/gofiber/fiber/v2 v2.48.0 h1:cRVMCb9aUJDsyHxGFLwz/sGzDggdailZZyptU9F9cU0= 4 | github.com/gofiber/fiber/v2 v2.48.0/go.mod h1:xqJgfqrc23FJuqGOW6DVgi3HyZEm2Mn9pRqUb2kHSX8= 5 | github.com/gofiber/template v1.8.2 h1:PIv9s/7Uq6m+Fm2MDNd20pAFFKt5wWs7ZBd8iV9pWwk= 6 | github.com/gofiber/template v1.8.2/go.mod h1:bs/2n0pSNPOkRa5VJ8zTIvedcI/lEYxzV3+YPXdBvq8= 7 | github.com/gofiber/template/html/v2 v2.0.5 h1:BKLJ6Qr940NjntbGmpO3zVa4nFNGDCi/IfUiDB9OC20= 8 | github.com/gofiber/template/html/v2 v2.0.5/go.mod h1:RCF14eLeQDCSUPp0IGc2wbSSDv6yt+V54XB/+Unz+LM= 9 | github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM= 10 | github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0= 11 | github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= 12 | github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 13 | github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= 14 | github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= 15 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= 16 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 17 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 18 | github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= 19 | github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 20 | github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= 21 | github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 22 | github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= 23 | github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= 24 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= 25 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 26 | github.com/valyala/fasthttp v1.48.0 h1:oJWvHb9BIZToTQS3MuQ2R3bJZiNSa2KiNdeI8A+79Tc= 27 | github.com/valyala/fasthttp v1.48.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= 28 | github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= 29 | github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= 30 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 31 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 32 | golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= 33 | golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 34 | -------------------------------------------------------------------------------- /server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gofiber/fiber/v2" 5 | "github.com/gofiber/template/html/v2" 6 | ) 7 | 8 | func main() { 9 | engine := html.New("./views", ".html") 10 | app := fiber.New(fiber.Config{Views: engine}) 11 | 12 | app.Get("/", func(c *fiber.Ctx) error { 13 | return c.Render("index", fiber.Map{}) 14 | }) 15 | 16 | app.Get("/search", func(c *fiber.Ctx) error { 17 | ticker := c.Query("ticker") 18 | results := SearchTicker(ticker) 19 | 20 | return c.Render("results", fiber.Map{ 21 | "Results": results, 22 | }) 23 | }) 24 | 25 | app.Get("/values/:ticker", func(c *fiber.Ctx) error { 26 | ticker := c.Params("ticker") 27 | values := GetDailyValues(ticker) 28 | 29 | return c.Render("values", fiber.Map{ 30 | "Ticker": ticker, 31 | "Values": values, 32 | }) 33 | }) 34 | 35 | app.Listen(":3000") 36 | } 37 | -------------------------------------------------------------------------------- /stocks.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "io" 6 | "net/http" 7 | "strings" 8 | 9 | "github.com/gofiber/fiber/v2/log" 10 | ) 11 | 12 | const PoligonPath = "https://api.polygon.io" 13 | const ApiKey = "apiKey=" 14 | 15 | const TickerPath = PoligonPath + "/v3/reference/tickers" 16 | const DailyValuesPath = PoligonPath + "/v1/open-close" 17 | 18 | type Stock struct { 19 | Ticker string `json:"ticker"` 20 | Name string `json:"name"` 21 | } 22 | 23 | type SearchResult struct { 24 | Results []Stock `json:"results"` 25 | } 26 | 27 | type Values struct { 28 | Symbol string `json:"symbol"` 29 | Open float64 `json:"open"` 30 | High float64 `json:"high"` 31 | Low float64 `json:"low"` 32 | Close float64 `json:"close"` 33 | } 34 | 35 | func Fetch(path string) string { 36 | resp, err := http.Get(path) 37 | if err != nil { 38 | log.Fatal(err) 39 | } 40 | 41 | body, err := io.ReadAll(resp.Body) 42 | if err != nil { 43 | log.Fatal(err) 44 | } 45 | 46 | return string(body) 47 | } 48 | 49 | func SearchTicker(ticker string) []Stock { 50 | body := Fetch(TickerPath + "?" + ApiKey + "&ticker=" + strings.ToUpper(ticker)) 51 | 52 | data := SearchResult{} 53 | json.Unmarshal([]byte(string(body)), &data) 54 | 55 | return data.Results 56 | } 57 | 58 | func GetDailyValues(ticker string) Values { 59 | body := Fetch(DailyValuesPath + "/" + strings.ToUpper(ticker) + "/2023-09-15/?" + ApiKey) 60 | 61 | data := Values{} 62 | json.Unmarshal([]byte(string(body)), &data) 63 | 64 | return data 65 | } 66 | -------------------------------------------------------------------------------- /views/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 15 |
16 | 17 |
18 |
19 | 20 | -------------------------------------------------------------------------------- /views/results.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /views/values.html: -------------------------------------------------------------------------------- 1 |

{{.Ticker}}

2 | --------------------------------------------------------------------------------