基于Go语言的股价提醒网页系统

2025年2月21日 999+浏览

一、需求分析

股价提醒系统具备以下基本功能:

  1. 实时获取股价:能够从金融数据接口获取指定股票的实时价格。
  2. 设置提醒条件:用户可以设置目标股价,当股价达到设定值时触发提醒。
  3. 提醒通知:通过邮件(或其他方式)向用户发送提醒信息。

二、技术选型

  1. 数据获取:使用第三方金融数据 API,如Alpha Vantage(https://www.alphavantage.co/) ,它提供丰富的金融数据,且有免费的使用额度。
  2. 邮件发送:Go 语言的net/smtp包可以实现邮件发送功能,用于发送提醒邮件。
  3. HTTP 服务器:利用net/http包搭建一个简单的 HTTP 服务器,方便用户设置提醒条件。

三、项目搭建

创建Go 项目(stock_alert_system),并初始化 Go 模块:

mkdir stock_alert_system
cd stock_alert_system
go mod init stock_alert_system

四、代码实现

1. 获取股价

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
)

type StockData struct {
    TimeSeriesDaily struct {
        "TimeSeriesDaily": map[string]map[string]string
    }
}

func getStockPrice(symbol string, apiKey string) (float64, error) {
    url := fmt.Sprintf("https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=%s&apikey=%s", symbol, apiKey)
    resp, err := http.Get(url)
    if err!= nil {
        return 0, err
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err!= nil {
        return 0, err
    }

    var stockData StockData
    err = json.Unmarshal(body, &stockData)
    if err!= nil {
        return 0, err
    }

    latestDate := ""
    for date := range stockData.TimeSeriesDaily {
        if latestDate == "" || date > latestDate {
            latestDate = date
        }
    }

    priceStr := stockData.TimeSeriesDaily[latestDate]["4. close"]
    var price float64
    _, err = fmt.Sscanf(priceStr, "%f", &price)
    if err!= nil {
        return 0, err
    }

    return price, nil
}

2. 发送邮件提醒

package main

import (
    "fmt"
    "log"
    "net/smtp"
)

func sendEmail(to, subject, body string) {
    from := "your_email@example.com"
    password := "your_email_password"

    msg := []byte("To: " + to + "\r\n" +
        "Subject: " + subject + "\r\n" +
        "\r\n" +
        body + "\r\n")

    auth := smtp.PlainAuth("", from, password, "smtp.example.com")

    err := smtp.SendMail("smtp.example.com:587", auth, from, []string{to}, msg)
    if err!= nil {
        log.Println("Error sending email:", err)
        return
    }

    fmt.Println("Email sent successfully!")
}

3. HTTP 服务器

package main

import (
    "fmt"
    "html/template"
    "log"
    "net/http"
)

type Alert struct {
    Symbol string
    Price  float64
    To     string
}

var alerts []Alert

func main() {
    http.HandleFunc("/", homeHandler)
    http.HandleFunc("/add_alert", addAlertHandler)

    log.Println("Server is running on http://localhost:8080")
    http.ListenAndServe(":8080", nil)
}

func homeHandler(w http.ResponseWriter, r *http.Request) {
    t, err := template.ParseFiles("templates/home.html")
    if err!= nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    t.Execute(w, nil)
}

func addAlertHandler(w http.ResponseWriter, r *http.Request) {
    if r.Method!= http.MethodPost {
        http.Error(w, "Only POST method is allowed", http.StatusMethodNotAllowed)
        return
    }

    symbol := r.FormValue("symbol")
    priceStr := r.FormValue("price")
    to := r.FormValue("to")

    var price float64
    _, err := fmt.Sscanf(priceStr, "%f", &price)
    if err!= nil {
        http.Error(w, "Invalid price format", http.StatusBadRequest)
        return
    }

    alert := Alert{
        Symbol: symbol,
        Price:  price,
        To:     to,
    }

    alerts = append(alerts, alert)

    go checkAlerts()

    http.Redirect(w, r, "/", http.StatusFound)
}

func checkAlerts() {
    apiKey := "your_api_key"
    for {
        for _, alert := range alerts {
            price, err := getStockPrice(alert.Symbol, apiKey)
            if err!= nil {
                log.Println("Error getting stock price:", err)
                continue
            }

            if price >= alert.Price {
                subject := fmt.Sprintf("股价提醒:%s 已达到目标价格", alert.Symbol)
                body := fmt.Sprintf("当前 %s 的股价为 %.2f,已达到您设定的目标价格 %.2f。", alert.Symbol, price, alert.Price)
                sendEmail(alert.To, subject, body)
            }
        }
    }
}

五、效果图