Basic IPO Calandar api work

This commit is contained in:
Ryan Ward 2026-05-05 11:38:03 -07:00
parent 64db958699
commit 72ff1c41a3
4 changed files with 132 additions and 0 deletions

1
.gitignore vendored
View File

@ -25,3 +25,4 @@ go.work.sum
# env file
.env
.apikey

View File

@ -0,0 +1,106 @@
package alphavantage
import (
"encoding/csv"
"fmt"
"io"
"net/http"
"strconv"
"time"
)
// IPOEvent represents a single row from the Alpha Vantage IPO Calendar CSV
type IPOEvent struct {
Symbol string `json:"symbol"`
Name string `json:"name"`
IPODate time.Time `json:"ipo_date"`
PriceRangeLow float64 `json:"price_range_low"`
PriceRangeHigh float64 `json:"price_range_high"`
Currency string `json:"currency"`
Exchange string `json:"exchange"`
}
// FetchIPOCalendar fetches the CSV data from Alpha Vantage and parses it into a slice of IPOEvent
func FetchIPOCalendar(apiKey string) ([]IPOEvent, error) {
url := fmt.Sprintf("https://www.alphavantage.co/query?function=IPO_CALENDAR&apikey=%s", apiKey)
// 1. Make the HTTP Request
resp, err := http.Get(url)
if err != nil {
return nil, fmt.Errorf("failed to fetch data: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("bad status code: %d", resp.StatusCode)
}
// 2. Initialize CSV reader
reader := csv.NewReader(resp.Body)
// Read the header row first to skip it
_, err = reader.Read()
if err != nil {
return nil, fmt.Errorf("failed to read CSV header: %w", err)
}
var events []IPOEvent
// 3. Iterate through CSV records
for {
record, err := reader.Read()
if err == io.EOF {
break // End of file
}
if err != nil {
return nil, fmt.Errorf("error reading csv record: %w", err)
}
// Map CSV columns to Struct
// Index mapping: 0:symbol, 1:name, 2:ipoDate, 3:priceRangeLow, 4:priceRangeHigh, 5:currency, 6:exchange
event, err := mapRecordToIPOEvent(record)
if err != nil {
// We log the error but continue processing other rows
fmt.Printf("Skipping row due to error: %v\n", err)
continue
}
events = append(events, event)
}
return events, nil
}
// mapRecordToIPOEvent handles the type conversion for a single CSV row
func mapRecordToIPOEvent(record []string) (IPOEvent, error) {
if len(record) < 7 {
return IPOEvent{}, fmt.Errorf("insufficient columns in record")
}
// Parse Date (Format: 2026-05-05)
ipoDate, err := time.Parse("2006-01-02", record[2])
if err != nil {
return IPOEvent{}, fmt.Errorf("invalid date format: %v", err)
}
// Parse Price Low
priceLow, err := strconv.ParseFloat(record[3], 64)
if err != nil {
return IPOEvent{}, fmt.Errorf("invalid price low: %v", err)
}
// Parse Price High
priceHigh, err := strconv.ParseFloat(record[4], 64)
if err != nil {
return IPOEvent{}, fmt.Errorf("invalid price high: %v", err)
}
return IPOEvent{
Symbol: record[0],
Name: record[1],
IPODate: ipoDate,
PriceRangeLow: priceLow,
PriceRangeHigh: priceHigh,
Currency: record[5],
Exchange: record[6],
}, nil
}

3
go.mod Normal file
View File

@ -0,0 +1,3 @@
module gitea.epicknex.ddns.net/epicknex/gamba-gods
go 1.26.2

22
main.go Normal file
View File

@ -0,0 +1,22 @@
package main
import (
"fmt"
"os"
"gitea.epicknex.ddns.net/epicknex/gamba-gods/api/alphavantage"
)
func main() {
data, err := os.ReadFile(".apikey")
if err != nil {
panic(err)
}
events, err := alphavantage.FetchIPOCalendar(string(data))
if err != nil {
fmt.Println("Error:", err)
}
for _, event := range events {
fmt.Printf("%+v\n", event) // Print the IPOEvent struct
}
}