github.com/diadata-org/diadata@v1.4.593/internal/pkg/ratescrapers/updateSOFR.go (about)

     1  package ratescrapers
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/xml"
     6  	"fmt"
     7  	"os"
     8  	"regexp"
     9  	"strconv"
    10  	"time"
    11  
    12  	models "github.com/diadata-org/diadata/pkg/model"
    13  	utils "github.com/diadata-org/diadata/pkg/utils"
    14  	log "github.com/sirupsen/logrus"
    15  )
    16  
    17  type (
    18  
    19  	// Define the fields associated with the rss document.
    20  	RssSOFR struct {
    21  		Channel Channel `xml:"channel"`
    22  		Item    Item    `xml:"item"`
    23  	}
    24  	Channel struct {
    25  		Title       string `xml:"title"`
    26  		Link        string `xml:"link"`
    27  		Description string `xml:"description"`
    28  	}
    29  	Item struct {
    30  		Title       string     `xml:"title"`
    31  		Link        string     `xml:"link"`
    32  		Description string     `xml:"description"`
    33  		Date        string     `xml:"date"`
    34  		Statistics  Statistics `xml:"statistics"`
    35  	}
    36  	Statistics struct {
    37  		Country    string `xml:"country"`
    38  		InstAbbrev string `xml:"institutionAbbrev"`
    39  		Rate       Rate   `xml:"interestRate"`
    40  	}
    41  	Rate struct {
    42  		Value    string `xml:"value"`
    43  		RateType string `xml:"rateType"`
    44  	}
    45  )
    46  
    47  // UpdateSOFR makes a GET request from an rss feed and sends updated value through
    48  // Channel s.chanInterestRate
    49  func (s *RateScraper) UpdateSOFR() error {
    50  	log.Printf("SOFRScraper update")
    51  
    52  	XMLdata, _, err := utils.GetRequest("https://apps.newyorkfed.org/rss/feeds/sofr")
    53  
    54  	if err != nil {
    55  		return err
    56  	}
    57  
    58  	// Decode the body
    59  	rss := new(RssSOFR)
    60  	buffer := bytes.NewBuffer(XMLdata)
    61  	decoded := xml.NewDecoder(buffer)
    62  	err = decoded.Decode(rss)
    63  
    64  	if err != nil {
    65  		fmt.Println(err)
    66  		os.Exit(1)
    67  	}
    68  
    69  	// Collext entries of InterestRate struct -----------------------------------
    70  	symbol := rss.Item.Statistics.Rate.RateType
    71  
    72  	// Convert interest rate from string to float64
    73  	rate, err := strconv.ParseFloat(rss.Item.Statistics.Rate.Value, 64)
    74  	if err != nil {
    75  		fmt.Println(err)
    76  	}
    77  
    78  	// Convert time string to Time type in UTC and pass date (without daytime)
    79  	dateTime, err := time.Parse(time.RFC3339, rss.Item.Date)
    80  	if err != nil {
    81  		fmt.Println(err)
    82  	} else {
    83  		dateTime = dateTime.UTC()
    84  	}
    85  
    86  	// Extract effective date from title
    87  	titleString := rss.Item.Title
    88  	dateRegexp, _ := regexp.Compile(`\d{4}-\d{2}-\d{2}`)
    89  	foundDate := dateRegexp.FindString(titleString)
    90  	effDate, err := time.Parse("2006-01-02", foundDate)
    91  	if err != nil {
    92  		log.Errorf("Error parsing the effective date of %v", symbol)
    93  	}
    94  
    95  	t := &models.InterestRate{
    96  		Symbol:          symbol,
    97  		Value:           rate,
    98  		PublicationTime: dateTime,
    99  		EffectiveDate:   effDate,
   100  		Source:          "FED",
   101  	}
   102  
   103  	// Send new data through channel chanInterestRate
   104  	log.Printf("Write interestRate %#v in %v\n", t, s.chanInterestRate)
   105  	s.chanInterestRate <- t
   106  
   107  	log.Info("Update complete")
   108  
   109  	return err
   110  }