github.com/diadata-org/diadata@v1.4.593/pkg/model/volumes.go (about)

     1  package models
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"strconv"
     8  	"time"
     9  
    10  	"github.com/diadata-org/diadata/pkg/dia"
    11  )
    12  
    13  const (
    14  	WindowVolume = 60 * 60 * 24
    15  )
    16  
    17  var (
    18  	volumeKey = "VOL" + strconv.Itoa(dia.BlockSizeSeconds)
    19  )
    20  
    21  // GetVolumeInflux returns the volume of @asset on @exchange using the VOL120 filter in the given time-range.
    22  // Both, @asset and @exchange may be empty.
    23  // If @starttime,@endtime are empty, the last 24h are taken into account.
    24  func (datastore *DB) GetVolumeInflux(asset dia.Asset, exchange string, starttime time.Time, endtime time.Time) (*float64, error) {
    25  
    26  	if endtime.IsZero() {
    27  		endtime = time.Now()
    28  		starttime = endtime.AddDate(0, 0, -1)
    29  	}
    30  
    31  	var q string
    32  
    33  	if asset == (dia.Asset{}) {
    34  		queryString := `
    35  		SELECT SUM(value) 
    36  		FROM %s 
    37  		WHERE exchange='%s' 
    38  		AND filter='%s' 
    39  		AND time > %d AND time<= %d
    40  		`
    41  		q = fmt.Sprintf(queryString, influxDbFiltersTable, exchange, volumeKey, starttime.UnixNano(), endtime.UnixNano())
    42  	} else if exchange == "" {
    43  		queryString := `
    44  		SELECT SUM(value) 
    45  		FROM %s 
    46  		WHERE address='%s' AND blockchain='%s' 
    47  		AND exchange=''
    48  		AND filter='%s' 
    49  		AND time > %d AND time<= %d
    50  		`
    51  		q = fmt.Sprintf(queryString, influxDbFiltersTable, asset.Address, asset.Blockchain, volumeKey, starttime.UnixNano(), endtime.UnixNano())
    52  	} else {
    53  		queryString := `
    54  		SELECT SUM(value) 
    55  		FROM %s 
    56  		WHERE address='%s' AND blockchain='%s' 
    57  		AND exchange='%s' 
    58  		AND filter='%s' 
    59  		AND time > %d AND time<= %d
    60  		`
    61  		q = fmt.Sprintf(queryString, influxDbFiltersTable, asset.Address, asset.Blockchain, exchange, volumeKey, starttime.UnixNano(), endtime.UnixNano())
    62  	}
    63  
    64  	var errorString string
    65  	res, err := queryInfluxDB(datastore.influxClient, q)
    66  	if err != nil {
    67  		log.Errorln("GetVolumeInflux ", err)
    68  		return nil, err
    69  	}
    70  
    71  	if len(res) > 0 && len(res[0].Series) > 0 {
    72  
    73  		var result float64
    74  		v, o := res[0].Series[0].Values[0][1].(json.Number)
    75  		if o {
    76  			result, err = v.Float64()
    77  			if err != nil {
    78  				log.Error(err)
    79  				return nil, err
    80  			}
    81  			return &result, nil
    82  		}
    83  		errorString = "error on parsing row 1"
    84  		return nil, errors.New(errorString)
    85  
    86  	} else {
    87  		volume := float64(0)
    88  		log.Warnf("no volume on %s in influx filter table", exchange)
    89  		return &volume, nil
    90  	}
    91  }
    92  
    93  // Get24HoursAssetVolume returns the 24h trading volume of @asset across exchanges.
    94  func (datastore *DB) Get24HoursAssetVolume(asset dia.Asset) (*float64, error) {
    95  	endtime := time.Now()
    96  	return datastore.GetVolumeInflux(asset, "", endtime.AddDate(0, 0, -1), endtime)
    97  }
    98  
    99  // Get24HoursExchangeVolume returns 24h trade volume on @exchange using VOL120 filtered data from influx.
   100  func (datastore *DB) Get24HoursExchangeVolume(exchange string) (*float64, error) {
   101  	endtime := time.Now()
   102  	return datastore.GetVolumeInflux(dia.Asset{}, exchange, endtime.AddDate(0, 0, -1), endtime)
   103  }
   104  
   105  // Returns aggregated volumes from filters measurement on all exchanges.
   106  func (datastore *DB) GetVolumesAllExchanges(asset dia.Asset, starttime time.Time, endtime time.Time) (exchVolumes dia.ExchangeVolumesList, err error) {
   107  	q := fmt.Sprintf(
   108  		`SELECT SUM(value) 
   109  		FROM %s 
   110  		WHERE filter='VOL120' 
   111  		AND address='%s' 
   112  		AND blockchain='%s'
   113  		AND exchange!='' 
   114  		AND time>%d 
   115  		AND time<=%d 
   116  		GROUP BY exchange`,
   117  		influxDbFiltersTable,
   118  		asset.Address,
   119  		asset.Blockchain,
   120  		starttime.UnixNano(),
   121  		endtime.UnixNano(),
   122  	)
   123  
   124  	res, err := queryInfluxDB(datastore.influxClient, q)
   125  	if err != nil {
   126  		log.Errorln("GetLastTrades", err)
   127  		return
   128  	}
   129  
   130  	if len(res) > 0 && len(res[0].Series) > 0 {
   131  		for i, group := range res[0].Series {
   132  			var exchangevolume dia.ExchangeVolume
   133  			if val, ok := group.Tags["exchange"]; ok {
   134  				exchangevolume.Exchange = val
   135  			}
   136  			if len(group.Values) > 0 && len(group.Values[0]) > 1 {
   137  				exchangevolume.Volume, err = group.Values[0][1].(json.Number).Float64()
   138  				if err != nil {
   139  					return
   140  				}
   141  			}
   142  			exchVolumes.Volumes = append(exchVolumes.Volumes, exchangevolume)
   143  			if i == 0 {
   144  				exchVolumes.Timestamp, err = time.Parse(time.RFC3339, res[0].Series[0].Values[0][0].(string))
   145  				if err != nil {
   146  					return
   147  				}
   148  			}
   149  		}
   150  
   151  	} else {
   152  		log.Error("Empty response GetVolumesAllExchanges")
   153  	}
   154  	return
   155  }
   156  
   157  func (datastore *DB) GetExchangePairVolumes(asset dia.Asset, starttime time.Time, endtime time.Time, threshold float64) (map[string][]dia.PairVolume, error) {
   158  	volumeMap := make(map[string][]dia.PairVolume)
   159  
   160  	query := fmt.Sprintf(
   161  		`
   162  		SELECT SUM(multiplication),COUNT(*)
   163  		FROM (
   164  			SELECT ABS(estimatedUSDPrice*volume)
   165  			AS multiplication
   166  			FROM %s
   167  			WHERE quotetokenaddress='%s'
   168  			AND quotetokenblockchain='%s'
   169  			AND basetokenaddress!=''
   170  			AND time>%d
   171  			AND time<=%d
   172  			)
   173  		GROUP BY "exchange","basetokenaddress","basetokenblockchain","pooladdress"
   174  		`,
   175  		influxDbTradesTable,
   176  		asset.Address,
   177  		asset.Blockchain,
   178  		starttime.UnixNano(),
   179  		endtime.UnixNano(),
   180  	)
   181  
   182  	res, err := queryInfluxDB(datastore.influxClient, query)
   183  	if err != nil {
   184  		return volumeMap, err
   185  	}
   186  
   187  	if len(res) > 0 && len(res[0].Series) > 0 {
   188  		for _, row := range res[0].Series {
   189  			if len(row.Values[0]) > 1 {
   190  				var (
   191  					pairvolume dia.PairVolume
   192  					err        error
   193  				)
   194  
   195  				exchange := row.Tags["exchange"]
   196  				pairvolume.Volume, err = row.Values[0][1].(json.Number).Float64()
   197  				if err != nil {
   198  					log.Warn("parse volume: ", err)
   199  				}
   200  				if !(pairvolume.Volume >= threshold) {
   201  					continue
   202  				}
   203  				pairvolume.TradesCount, err = row.Values[0][2].(json.Number).Int64()
   204  				if err != nil {
   205  					log.Warn("parse trades count: ", err)
   206  				}
   207  				pairvolume.Pair = dia.Pair{
   208  					QuoteToken: dia.Asset{Blockchain: asset.Blockchain, Address: asset.Address},
   209  					BaseToken:  dia.Asset{Blockchain: row.Tags["basetokenblockchain"], Address: row.Tags["basetokenaddress"]},
   210  				}
   211  				pairvolume.PoolAddress = row.Tags["pooladdress"]
   212  				volumeMap[exchange] = append(volumeMap[exchange], pairvolume)
   213  			}
   214  		}
   215  	}
   216  	return volumeMap, nil
   217  }
   218  
   219  func (datastore *DB) GetExchangePairVolume(
   220  	ep dia.ExchangePair,
   221  	pooladdress string,
   222  	starttime time.Time,
   223  	endtime time.Time,
   224  	threshold float64,
   225  ) (volume float64, tradesCount int64, err error) {
   226  	query := fmt.Sprintf(
   227  		`
   228  		SELECT SUM(multiplication),COUNT(*)
   229  		FROM (
   230  			SELECT ABS(estimatedUSDPrice*volume)
   231  			AS multiplication
   232  			FROM %s
   233  			WHERE quotetokenaddress='%s'
   234  			AND quotetokenblockchain='%s'
   235  			AND basetokenaddress='%s'
   236  			AND basetokenblockchain='%s'
   237  			AND pooladdress='%s'
   238  			AND exchange='%s'
   239  			AND time>%d
   240  			AND time<=%d
   241  			)
   242  		`,
   243  		influxDbTradesTable,
   244  		ep.UnderlyingPair.QuoteToken.Address,
   245  		ep.UnderlyingPair.QuoteToken.Blockchain,
   246  		ep.UnderlyingPair.BaseToken.Address,
   247  		ep.UnderlyingPair.BaseToken.Blockchain,
   248  		pooladdress,
   249  		ep.Exchange,
   250  		starttime.UnixNano(),
   251  		endtime.UnixNano(),
   252  	)
   253  
   254  	res, err := queryInfluxDB(datastore.influxClient, query)
   255  	if err != nil {
   256  		return
   257  	}
   258  
   259  	if len(res) > 0 && len(res[0].Series) > 0 {
   260  		volume, _ = res[0].Series[0].Values[0][1].(json.Number).Float64()
   261  		tradesCount, _ = res[0].Series[0].Values[0][2].(json.Number).Int64()
   262  	}
   263  	return
   264  }