add margin
All checks were successful
Build Docker Image / build (amd64) (push) Successful in 1m47s

This commit is contained in:
thuanle
2024-10-24 10:58:32 +07:00
parent b60fcb842d
commit 94a11e8d68
10 changed files with 98 additions and 30 deletions

View File

@@ -1,15 +1,5 @@
package binance
const (
AssetUsdt = "USDT"
AssetUsdc = "USDC"
AssetFdusd = "FDUSD"
AssetBtc = "BTC"
AssetBnb = "BNB"
AssetEth = "ETH"
AssetXrp = "XRP"
)
var SymbolPrefixList = []string{"1000"}
var SymbolSuffixMap = map[string]string{
"USDT": "",

View File

@@ -5,4 +5,5 @@ type IMarket interface {
GetAllFundRate() (map[string]float64, map[string]int64)
GetSpotPrice(symbol string) (float64, bool)
GetMarginInterestRates() map[string]float64
}

View File

@@ -6,7 +6,7 @@ import (
"strconv"
)
func (ms MarketData) GetFuturePrice(symbol string) (float64, float64, int64, bool) {
func (ms *MarketData) GetFuturePrice(symbol string) (float64, float64, int64, bool) {
p, ok := ms.futureMarkPrice[symbol]
if !ok {
return 0, 0, 0, false
@@ -14,7 +14,7 @@ func (ms MarketData) GetFuturePrice(symbol string) (float64, float64, int64, boo
return p, ms.futureFundingRate[symbol], ms.futureNextFundingTime[symbol], true
}
func (ms MarketData) StartFutureWsMarkPrice() error {
func (ms *MarketData) StartFutureWsMarkPrice() error {
_, _, err := futures.WsAllMarkPriceServe(ms.futureWsMarkPriceHandler, ms.futureWsErrHandler)
if err != nil {
return err
@@ -22,7 +22,7 @@ func (ms MarketData) StartFutureWsMarkPrice() error {
return nil
}
func (ms MarketData) futureWsMarkPriceHandler(event futures.WsAllMarkPriceEvent) {
func (ms *MarketData) futureWsMarkPriceHandler(event futures.WsAllMarkPriceEvent) {
for _, priceEvent := range event {
price, err := strconv.ParseFloat(priceEvent.MarkPrice, 64)
if err != nil {
@@ -40,11 +40,11 @@ func (ms MarketData) futureWsMarkPriceHandler(event futures.WsAllMarkPriceEvent)
}
}
func (ms MarketData) futureWsErrHandler(err error) {
func (ms *MarketData) futureWsErrHandler(err error) {
log.Debug().Err(err).Msg("Ws Error. Restart socket")
_ = ms.StartFutureWsMarkPrice()
}
func (ms MarketData) GetAllFundRate() (map[string]float64, map[string]int64) {
func (ms *MarketData) GetAllFundRate() (map[string]float64, map[string]int64) {
return ms.futureFundingRate, ms.futureNextFundingTime
}

View File

@@ -0,0 +1,65 @@
package market
import (
"github.com/go-resty/resty/v2"
"github.com/rs/zerolog/log"
"me.thuanle/bbot/internal/utils/convertx"
)
// Structs to parse the JSON response
type MarginInterestResponse struct {
Code string `json:"code"`
Message string `json:"message"`
Data []Asset `json:"data"`
}
type Asset struct {
AssetName string `json:"assetName"`
Specs []Spec `json:"specs"`
}
type Spec struct {
VipLevel string `json:"vipLevel"`
DailyInterestRate string `json:"dailyInterestRate"`
}
func (ms *MarketData) GetMarginInterestRates() map[string]float64 {
data := fetchMarginInterestRate()
// Map to store the interest rates for the requested tokens
rates := make(map[string]float64)
// Iterate over the fetched data and match tokens with VIP Level 0 interest rates
for _, asset := range data {
for _, spec := range asset.Specs {
if spec.VipLevel == "0" {
rateDaily := convertx.String2Float64(spec.DailyInterestRate, 0)
rates[asset.AssetName] = rateDaily
}
}
}
return rates
}
func fetchMarginInterestRate() []Asset {
url := "https://www.binance.com/bapi/margin/v1/friendly/margin/vip/spec/list-all"
// Create a new Resty client
client := resty.New()
// Send the GET request to the API
var response MarginInterestResponse
resp, err := client.R().
SetResult(&response).
Get(url)
if err != nil {
log.Err(err).
Str("status", resp.Status()).
Msg("Failed to fetch margin interest rates")
return nil
}
return response.Data
}

View File

@@ -6,12 +6,12 @@ import (
"strconv"
)
func (ms MarketData) GetSpotPrice(symbol string) (float64, bool) {
func (ms *MarketData) GetSpotPrice(symbol string) (float64, bool) {
p, ok := ms.spotPrice[symbol]
return p, ok
}
func (ms MarketData) StartSpotWsMarkPrice() error {
func (ms *MarketData) StartSpotWsMarkPrice() error {
_, _, err := binance.WsAllMarketsStatServe(ms.spotWsAllMarketsStatHandler, ms.spotWsErrHandler) //.WsAllMarkPriceServe(ms.futureWsMarkPriceHandler, ms.futureWsErrHandler)
if err != nil {
@@ -20,7 +20,7 @@ func (ms MarketData) StartSpotWsMarkPrice() error {
return nil
}
func (ms MarketData) spotWsAllMarketsStatHandler(event binance.WsAllMarketsStatEvent) {
func (ms *MarketData) spotWsAllMarketsStatHandler(event binance.WsAllMarketsStatEvent) {
for _, priceEvent := range event {
price, err := strconv.ParseFloat(priceEvent.LastPrice, 64)
if err != nil {
@@ -30,7 +30,7 @@ func (ms MarketData) spotWsAllMarketsStatHandler(event binance.WsAllMarketsStatE
}
}
func (ms MarketData) spotWsErrHandler(err error) {
func (ms *MarketData) spotWsErrHandler(err error) {
log.Debug().Err(err).Msg("Spot Ws Error. Restart socket")
_ = ms.StartSpotWsMarkPrice()
}

View File

@@ -31,13 +31,15 @@ func OnTokenInfoByToken(context telebot.Context, token string) error {
showStickerMode(context, token)
fp, fundRate, fundTime, ok := data.Market.GetFuturePrice(symbols[0])
marginRates := data.Market.GetMarginInterestRates()
tokenInterestRate := marginRates[strings.ToUpper(token)]
if !ok {
return nil
}
sSymbol := binancex.Future2SpotSymbol(symbols[0])
sp, _ := data.Market.GetSpotPrice(sSymbol)
_ = chat.ReplyMessage(context, view.RenderOnPriceMessage(symbols[0], sp, fp, fundRate, fundTime))
_ = chat.ReplyMessage(context, view.RenderOnPriceMessage(symbols[0], sp, fp, fundRate, fundTime, tokenInterestRate))
return nil
}

View File

@@ -35,19 +35,21 @@ func RenderPrice(price float64) string {
}
}
func RenderOnPriceMessage(symbol string, spotPrice float64, futurePrice float64, fundrate float64, fundtime int64) string {
func RenderOnPriceMessage(symbol string, spotPrice float64, futurePrice float64, fundrate float64, fundtime int64, marginRate float64) string {
return fmt.Sprintf(
"%s: %s\n"+
"Fund rate: %.4f%% %s in %s\n"+
"Spot: %s",
"Spot: %s\n"+
"Margin rate: %.3f%%",
RenderSymbolInfo(symbol), RenderPrice(futurePrice),
fundrate*100, IconOfFundingFeeDirection(fundrate), timex.CdMinuteStringTime(time.UnixMilli(fundtime)),
RenderPrice(spotPrice),
marginRate*365,
)
}
func RenderOnGetTopPricesMessage(symbols []string, price []float64, fundRate []float64) string {
t := helper.NewNoBorderTableWriter("", "Price", "Rate")
t := helper.NewNoBorderTableWriter("", "Price", "Fund")
mFmt := message.NewPrinter(language.AmericanEnglish)
for i, symbol := range symbols {
t.AppendRow(table.Row{

View File

@@ -7,5 +7,5 @@ import (
func RenderSymbolInfo(sym string) string {
token := binancex.Symbol2Token(sym)
return fmt.Sprintf("<a href=\"https://www.binance.com/futures/%s\">%s</a>", sym, token)
return fmt.Sprintf("#%s", token)
}