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

     1  package ratescrapers
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/xml"
     6  	"fmt"
     7  	"os"
     8  	"strconv"
     9  	"time"
    10  
    11  	models "github.com/diadata-org/diadata/pkg/model"
    12  	utils "github.com/diadata-org/diadata/pkg/utils"
    13  	log "github.com/sirupsen/logrus"
    14  )
    15  
    16  type (
    17  	CsafrRatesSecondaryFindByDateResponseAvg struct {
    18  		XMLName               xml.Name                 `xml:"safrRatesSecondaryFindByDateResponse,omitempty" json:"safrRatesSecondaryFindByDateResponse,omitempty"`
    19  		CsafrRatesFindItemAvg []*CsafrRatesFindItemAvg `xml:"safrRatesFindItem,omitempty" json:"safrRatesFindItem,omitempty"`
    20  	}
    21  
    22  	CsafrRatesFindItemAvg struct {
    23  		XMLName           xml.Name           `xml:"safrRatesFindItem,omitempty" json:"safrRatesFindItem,omitempty"`
    24  		CrateOperationAvg *CrateOperationAvg `xml:"rateOperation,omitempty" json:"rateOperation,omitempty"`
    25  	}
    26  
    27  	CrateOperationAvg struct {
    28  		XMLName             xml.Name             `xml:"rateOperation,omitempty" json:"rateOperation,omitempty"`
    29  		CeffectiveDateAvg   *CeffectiveDateAvg   `xml:"effectiveDate,omitempty" json:"effectiveDate,omitempty"`
    30  		CinsertTimestampAvg *CinsertTimestampAvg `xml:"insertTimestamp,omitempty" json:"insertTimestamp,omitempty"`
    31  		CTenor1Avg          *CTenor1Avg          `xml:"tenor1,omitempty" json:"tenor1,omitempty"`
    32  		CTenor2Avg          *CTenor2Avg          `xml:"tenor2,omitempty" json:"tenor2,omitempty"`
    33  		CTenor3Avg          *CTenor3Avg          `xml:"tenor3,omitempty" json:"tenor3,omitempty"`
    34  	}
    35  
    36  	CeffectiveDateAvg struct {
    37  		XMLName     xml.Name `xml:"effectiveDate,omitempty" json:"effectiveDate,omitempty"`
    38  		CEffDateAvg string   `xml:",chardata" json:",omitempty"`
    39  	}
    40  
    41  	CinsertTimestampAvg struct {
    42  		XMLName       xml.Name `xml:"insertTimestamp,omitempty" json:"insertTimestamp,omitempty"`
    43  		CTimestampAvg string   `xml:",chardata" json:",omitempty"`
    44  	}
    45  
    46  	CTenor1Avg struct {
    47  		XMLName    xml.Name `xml:"tenor1,omitempty" json:"tenor1,omitempty"`
    48  		CValue1Avg string   `xml:",chardata" json:",omitempty"`
    49  	}
    50  
    51  	CTenor2Avg struct {
    52  		XMLName    xml.Name `xml:"tenor2,omitempty" json:"tenor1,omitempty"`
    53  		CValue2Avg string   `xml:",chardata" json:",omitempty"`
    54  	}
    55  
    56  	CTenor3Avg struct {
    57  		XMLName    xml.Name `xml:"tenor3,omitempty" json:"tenor1,omitempty"`
    58  		CValue3Avg string   `xml:",chardata" json:",omitempty"`
    59  	}
    60  )
    61  
    62  // UpdateSAFRAvgs makes a GET request from an rss feed and sends updated value through
    63  // Channel s.chanInterestRate
    64  func (s *RateScraper) UpdateSAFRAvgs() error {
    65  	log.Printf("SAFRScraper update")
    66  
    67  	XMLdata, _, err := utils.GetRequest("https://apps.newyorkfed.org/api/safrate/r1")
    68  
    69  	if err != nil {
    70  		return err
    71  	}
    72  
    73  	// Decode the body
    74  	rss := new(CsafrRatesSecondaryFindByDateResponseAvg)
    75  	buffer := bytes.NewBuffer(XMLdata)
    76  	decoded := xml.NewDecoder(buffer)
    77  	err = decoded.Decode(rss)
    78  
    79  	if err != nil {
    80  		fmt.Println(err)
    81  		os.Exit(1)
    82  	}
    83  
    84  	// Pick the actual value out of all data
    85  	numData := len(rss.CsafrRatesFindItemAvg)
    86  	ActData := rss.CsafrRatesFindItemAvg[numData-1]
    87  
    88  	// Convert rates from string to float64
    89  	rate1, err := strconv.ParseFloat(ActData.CrateOperationAvg.CTenor1Avg.CValue1Avg, 64)
    90  	if err != nil {
    91  		fmt.Println(err)
    92  	}
    93  	rate2, err := strconv.ParseFloat(ActData.CrateOperationAvg.CTenor2Avg.CValue2Avg, 64)
    94  	if err != nil {
    95  		fmt.Println(err)
    96  	}
    97  
    98  	rate3, err := strconv.ParseFloat(ActData.CrateOperationAvg.CTenor3Avg.CValue3Avg, 64)
    99  	if err != nil {
   100  		fmt.Println(err)
   101  	}
   102  
   103  	// Convert time string to Time type in UTC and pass date (without daytime)
   104  	dateTime, err := time.Parse(time.RFC3339, ActData.CrateOperationAvg.CinsertTimestampAvg.CTimestampAvg)
   105  	if err != nil {
   106  		fmt.Println(err)
   107  	} else {
   108  		dateTime = dateTime.Round(time.Second).UTC()
   109  	}
   110  	effDate, err := time.Parse("2006-01-02", ActData.CrateOperationAvg.CeffectiveDateAvg.CEffDateAvg)
   111  	if err != nil {
   112  		log.Error("Error parsing effective date for SOFRXXX", err)
   113  	}
   114  
   115  	t1 := &models.InterestRate{
   116  		Symbol:          "SOFR30",
   117  		Value:           rate1,
   118  		PublicationTime: dateTime,
   119  		EffectiveDate:   effDate,
   120  		Source:          "FED",
   121  	}
   122  
   123  	t2 := &models.InterestRate{
   124  		Symbol:          "SOFR90",
   125  		Value:           rate2,
   126  		PublicationTime: dateTime,
   127  		EffectiveDate:   effDate,
   128  		Source:          "FED",
   129  	}
   130  
   131  	t3 := &models.InterestRate{
   132  		Symbol:          "SOFR180",
   133  		Value:           rate3,
   134  		PublicationTime: dateTime,
   135  		EffectiveDate:   effDate,
   136  		Source:          "FED",
   137  	}
   138  
   139  	// Send new data through channel chanInterestRate
   140  	log.Printf("Write interestRate %#v in %v\n", t1, s.chanInterestRate)
   141  	s.chanInterestRate <- t1
   142  
   143  	log.Printf("Write interestRate %#v in %v\n", t2, s.chanInterestRate)
   144  	s.chanInterestRate <- t2
   145  
   146  	log.Printf("Write interestRate %#v in %v\n", t3, s.chanInterestRate)
   147  	s.chanInterestRate <- t3
   148  
   149  	log.Info("Update complete")
   150  
   151  	return err
   152  }