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 }