github.com/diadata-org/diadata@v1.4.593/internal/pkg/static-scrapers/historySAFRAvgs.go (about)

     1  package staticscrapers
     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  // WriteHistoricSAFRAvgs makes a GET request to fetch the historic data of the SOFR
    63  // average index and writes it into the redis database.
    64  func WriteHistoricSAFRAvgs(ds models.Datastore) error {
    65  	log.Printf("Writing historic SAFR average values")
    66  
    67  	// Get rss from fed webpage
    68  	XMLdata, _, err := utils.GetRequest("https://apps.newyorkfed.org/api/safrate/r1")
    69  
    70  	if err != nil {
    71  		return err
    72  	}
    73  
    74  	// Decode the body
    75  	rss := new(CsafrRatesSecondaryFindByDateResponseAvg)
    76  	buffer := bytes.NewBuffer(XMLdata)
    77  	decoded := xml.NewDecoder(buffer)
    78  	err = decoded.Decode(rss)
    79  
    80  	if err != nil {
    81  		fmt.Println(err)
    82  		os.Exit(1)
    83  	}
    84  
    85  	// A slice containing all historic data
    86  	histDataSlice := rss.CsafrRatesFindItemAvg
    87  	numData := len(histDataSlice)
    88  
    89  	for i := 0; i < numData; i++ {
    90  		var rate1 float64
    91  		var rate2 float64
    92  		var rate3 float64
    93  		var dateTime time.Time
    94  		var effDate time.Time
    95  
    96  		// Convert rates from string to float64
    97  		rate1, err = strconv.ParseFloat(histDataSlice[i].CrateOperationAvg.CTenor1Avg.CValue1Avg, 64)
    98  		if err != nil {
    99  			fmt.Println(err)
   100  		}
   101  		rate2, err = strconv.ParseFloat(histDataSlice[i].CrateOperationAvg.CTenor2Avg.CValue2Avg, 64)
   102  		if err != nil {
   103  			fmt.Println(err)
   104  		}
   105  
   106  		rate3, err = strconv.ParseFloat(histDataSlice[i].CrateOperationAvg.CTenor3Avg.CValue3Avg, 64)
   107  		if err != nil {
   108  			fmt.Println(err)
   109  		}
   110  
   111  		// Convert time string to Time type in UTC and pass date (without daytime)
   112  		dateTime, err = time.Parse(time.RFC3339, histDataSlice[i].CrateOperationAvg.CinsertTimestampAvg.CTimestampAvg)
   113  		if err != nil {
   114  			log.Error("Error parsing publishing time for SOFRXXX: ", err)
   115  		} else {
   116  			dateTime = dateTime.Round(time.Second).UTC()
   117  		}
   118  
   119  		effDate, err = time.Parse("2006-01-02", histDataSlice[i].CrateOperationAvg.CeffectiveDateAvg.CEffDateAvg)
   120  		if err != nil {
   121  			log.Error("Error parsing effective date for SOFRXXX: ", err)
   122  		}
   123  
   124  		t1 := models.InterestRate{
   125  			Symbol:          "SOFR30",
   126  			Value:           rate1,
   127  			PublicationTime: dateTime,
   128  			EffectiveDate:   effDate,
   129  			Source:          "FED",
   130  		}
   131  
   132  		t2 := models.InterestRate{
   133  			Symbol:          "SOFR90",
   134  			Value:           rate2,
   135  			PublicationTime: dateTime,
   136  			EffectiveDate:   effDate,
   137  			Source:          "FED",
   138  		}
   139  
   140  		t3 := models.InterestRate{
   141  			Symbol:          "SOFR180",
   142  			Value:           rate3,
   143  			PublicationTime: dateTime,
   144  			EffectiveDate:   effDate,
   145  			Source:          "FED",
   146  		}
   147  
   148  		err = ds.SetInterestRate(&t1)
   149  		if err != nil {
   150  			log.Error(err)
   151  		}
   152  		err = ds.SetInterestRate(&t2)
   153  		if err != nil {
   154  			log.Error(err)
   155  		}
   156  		err = ds.SetInterestRate(&t3)
   157  		if err != nil {
   158  			log.Error(err)
   159  		}
   160  
   161  	}
   162  
   163  	log.Info("Writing historic SAFR average data complete.")
   164  
   165  	return err
   166  }