diff --git a/exp/ticker/internal/gql/main.go b/exp/ticker/internal/gql/main.go index eb600114a1..ea93e473b2 100644 --- a/exp/ticker/internal/gql/main.go +++ b/exp/ticker/internal/gql/main.go @@ -59,6 +59,7 @@ type partialMarket struct { Close float64 IntervalStart graphql.Time FirstLedgerCloseTime graphql.Time + LastLedgerCloseTime graphql.Time OrderbookStats orderbookStats } diff --git a/exp/ticker/internal/gql/resolvers_market.go b/exp/ticker/internal/gql/resolvers_market.go index 866ee555da..cefed3093e 100644 --- a/exp/ticker/internal/gql/resolvers_market.go +++ b/exp/ticker/internal/gql/resolvers_market.go @@ -112,6 +112,7 @@ func dbMarketToPartialMarket(dbMarket tickerdb.PartialMarket) *partialMarket { Close: dbMarket.Close, IntervalStart: graphql.Time{Time: dbMarket.IntervalStart}, FirstLedgerCloseTime: graphql.Time{Time: dbMarket.FirstLedgerCloseTime}, + LastLedgerCloseTime: graphql.Time{Time: dbMarket.LastLedgerCloseTime}, OrderbookStats: os, } } diff --git a/exp/ticker/internal/gql/static/bindata.go b/exp/ticker/internal/gql/static/bindata.go index a593582b36..45b400ec2d 100644 --- a/exp/ticker/internal/gql/static/bindata.go +++ b/exp/ticker/internal/gql/static/bindata.go @@ -125,36 +125,36 @@ func bindataGraphiqlhtml() (*asset, error) { } var _bindataSchemagql = []byte( - "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xdc\x54\x4f\x6f\xe3\xb6\x13\x3d\x4b\x9f\x62\x82\xbd\x24\x17\x1f\x7e\xf8" + - "\x9d\x84\xb6\x80\x93\xb4\x68\xd0\x78\xbb\x5d\x67\x8b\x02\x41\x51\x8c\xc5\xb1\x3c\x30\x45\x6a\x87\xa4\x13\x63\x91" + - "\xef\x5e\x90\x92\x1d\x4a\x4a\xd3\x7b\x4f\xd2\xfc\x79\xc3\x99\xc7\xc7\x71\xf5\x8e\x5a\x84\x6f\x65\xf1\x35\x90\x1c" + - "\x2b\x28\x7e\x8b\xdf\xf2\xa5\x2c\xfd\xb1\x23\x48\x56\x0c\x7f\x00\x21\x2f\x4c\x07\x02\xd4\x1a\x0e\xa8\x59\xa1\x27" + - "\x05\xe8\x1c\x79\x07\xd6\x80\xdf\x11\xac\x3d\x69\x8d\x02\x86\xfc\x93\x95\xfd\xa2\x2c\xfa\x78\x05\x8f\xcb\xf8\x73" + - "\xf1\xe7\x45\xf9\x4e\x31\x76\x2e\x90\xbc\x53\x6d\x48\xa8\xe0\xf1\x2e\xfd\xcd\xea\x79\x41\x45\xe0\x3c\x7a\x07\x5b" + - "\xb1\x6d\xaa\xa3\xd1\x79\xf8\xce\x84\xf6\x67\x1b\xc4\x2d\x1b\xfb\x03\xec\xe2\x5f\x44\x5e\x2a\xda\x62\xd0\x1e\xbe" + - "\x87\xff\xfd\xbf\x77\x5f\x2d\xc0\x76\x9e\xad\x41\xad\x8f\xd0\x89\x3d\xb0\x22\xa8\x6d\x30\x9e\x04\xd0\xa8\x88\xdb" + - "\xa0\xa3\x7e\x78\x60\xb3\xb5\xb0\xb5\x02\x5b\xd6\x9e\x84\x4d\xb3\x28\x8b\x16\x65\x4f\xde\x5d\x96\x45\x11\x53\xd3" + - "\xf4\x37\x56\x51\x05\x6b\x1f\x53\x72\x7f\x3f\x4b\x16\x19\xce\x7a\x0b\x94\x87\x66\xb8\x6c\xc4\x0a\xee\x8c\x2f\x8b" + - "\xab\x0a\x1e\x57\xa9\x95\x19\xf3\x4d\x23\xd4\x24\xda\x47\xa4\x59\xf9\x07\xce\x22\x3a\xf1\xf3\x26\x3d\x11\x63\xb0" + - "\x25\xb0\xdb\xf4\xdf\xd7\xec\x90\x05\x2e\x69\x11\x19\xf9\x00\x7f\xdc\xaf\xfe\xba\x7e\xb8\xb9\x1a\x93\x05\x42\x2e" + - "\x68\xef\x16\x65\xe1\xb9\xde\x93\x44\xce\x22\xf0\x23\xb6\xf4\xaf\xc3\x2d\xcf\x63\x9c\xc7\x7c\x29\x4b\x57\x63\x14" + - "\xce\x35\x37\x31\x71\xb0\x1e\xb8\xa5\x41\xd7\x89\xbe\xa8\xeb\x3a\x63\xf7\xe2\xa4\xaf\x65\x9d\x58\xce\xfc\x11\x94" + - "\x99\x26\xb4\x43\x8e\x4b\xad\x5c\x94\x05\x06\xbf\xfb\x4c\x5f\x03\x0b\xa9\x0a\xae\xad\xd5\x84\xe6\xec\x3f\xd8\x1a" + - "\x37\x9a\x46\x81\xb6\x3f\xe3\x27\x6d\x31\x15\xe8\x2f\xdb\x78\xb1\x5a\x93\xba\x3e\xde\xda\x16\xd9\x8c\x20\xa6\xde" + - "\xd9\xb9\x2a\xc6\x91\x87\x71\xab\xec\x92\x77\x99\x12\xc6\xad\x29\x76\x9d\xc6\xe3\x2d\xd5\xdc\xa2\x76\xd5\x40\x57" + - "\x9c\x2f\x63\x3e\x26\x92\xab\x33\xb3\xb6\x46\x71\x14\x80\xcb\x9c\x5b\x7e\x26\xf5\x31\xb4\x9b\x28\xc8\x73\xa1\x16" + - "\x9f\x67\x3e\x76\x5f\x8c\xe6\x96\xfd\xb8\x1b\x21\x45\x6d\xd2\xd5\x9d\x71\x5e\x42\x3d\x3d\xa1\xb6\x5a\xa3\x27\x41" + - "\xbd\x54\x4a\xc8\x39\x7a\x37\xba\xe6\xc6\xa0\x0f\x32\xc9\x0a\x26\xea\x3f\xf7\x45\xdd\x07\x37\x13\xc1\xdd\xed\x70" + - "\xb5\xa7\x5d\xd8\xeb\x2b\x8a\x26\x69\xfb\x13\xb2\x64\xa0\x37\x1f\x79\xee\x1f\x3f\xd6\x53\x2f\x6f\x3c\xf2\x49\x68" + - "\x86\x8b\x15\x7f\xb7\x3a\xc4\x2b\x3a\x89\x67\x00\x4c\xdd\xa9\xd1\x9b\x5e\x67\x3d\xf9\xb6\x23\xf3\x1a\xd7\xf6\xe9" + - "\xd5\xd8\x71\xb3\xcb\x2a\xee\xd0\x34\xf9\x09\xda\xba\xcc\xe4\x78\xdc\x01\xf5\xda\xa3\xf8\x2a\x3d\xad\x24\x02\x71" + - "\xfe\x9e\x54\x43\x72\x13\xf3\xa3\xfb\x1c\xb4\xa2\x48\x36\xd6\xee\xd7\x71\xd1\x54\xf0\xeb\xc8\x7e\xe5\x79\xfa\xa2" + - "\xdf\x63\xfc\xbf\xcc\xc3\xd8\x0f\xdf\x4a\x28\x36\xac\x86\x29\xce\xaf\x69\xc3\x6a\x3a\xed\x86\xd5\x0a\x9f\xf3\xcd" + - "\xb2\x9f\xa2\xd0\xed\xa7\x28\x74\xfb\x15\x67\x9c\xb8\x4e\x08\xd5\xd4\x5e\xb1\xfa\x64\x39\xdb\x5b\xa7\x6e\x7b\x99" + - "\xc6\xbb\xea\xc2\x46\x73\xfd\x0b\x1d\xf3\x85\x39\x5e\x28\x41\x74\xbe\x5c\x6d\xab\xbf\x7c\xbe\xcf\x97\x09\x29\x12" + - "\x8c\x0b\x60\x4d\x72\x18\xa9\x3f\xee\xd3\x99\xd3\x0b\x1a\xb7\x25\x99\x05\x9e\x68\xb3\x0c\x7e\xf7\xa3\x51\x5d\xdf" + - "\x75\xb6\xd3\x3a\xeb\xd8\xcf\x10\x56\x9a\x87\x27\xf6\x3e\x77\xbe\x94\x7f\x07\x00\x00\xff\xff\x3f\x67\xd7\xeb\x28" + - "\x09\x00\x00") + "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xe4\x54\xcd\x6e\xe3\x36\x10\x3e\x4b\x4f\x31\xc1\x5e\x36\x17\x1f\x8a\x9e" + + "\x84\xb6\x80\x93\xb4\x68\xd0\x78\xbb\x5d\x67\x8b\x02\x41\x51\x8c\xc5\xb1\x3c\x30\x45\x6a\x87\xa4\x13\x63\x91\x77" + + "\x2f\x48\xc9\x0e\x25\x65\xd3\x07\xe8\x49\x9a\x9f\x6f\x38\xf3\xf1\xe3\xb8\x7a\x47\x2d\xc2\xd7\xb2\xf8\x12\x48\x8e" + + "\x15\x14\x7f\xc4\x6f\xf9\x5c\x96\xfe\xd8\x11\x24\x2b\x86\xdf\x81\x90\x17\xa6\x03\x01\x6a\x0d\x07\xd4\xac\xd0\x93" + + "\x02\x74\x8e\xbc\x03\x6b\xc0\xef\x08\xd6\x9e\xb4\x46\x01\x43\xfe\xd1\xca\x7e\x51\x16\x7d\xbc\x82\x87\x65\xfc\xb9" + + "\xf8\xfb\xa2\x7c\xa3\x18\x3b\x17\x48\xde\xa8\x36\x24\x54\xf0\x70\x9b\xfe\x66\xf5\xbc\xa0\x22\x70\x1e\xbd\x83\xad" + + "\xd8\x36\xd5\xd1\xe8\x3c\xfc\x60\x42\xfb\xab\x0d\xe2\x96\x8d\xfd\x09\x76\xf1\x2f\x22\xdf\x2b\xda\x62\xd0\x1e\x7e" + + "\x84\xef\xbe\xef\xdd\x97\x0b\xb0\x9d\x67\x6b\x50\xeb\x23\x74\x62\x0f\xac\x08\x6a\x1b\x8c\x27\x01\x34\x2a\xe2\x36" + + "\xe8\xa8\x1f\x1e\xd8\x6c\x2d\x6c\xad\xc0\x96\xb5\x27\x61\xd3\x2c\xca\xa2\x45\xd9\x93\x77\xef\xcb\xa2\x88\xa9\x69" + + "\xfa\x6b\xab\xa8\x82\xb5\x8f\x29\xb9\xbf\x9f\x25\x8b\x0c\x67\xbd\x06\xca\x43\x33\x5c\x36\x62\x05\xb7\xc6\x97\xc5" + + "\x65\x05\x0f\xab\xd4\xca\x8c\xf9\xa6\x11\x6a\x12\xed\x23\xd2\xac\x7c\x83\xb3\x88\x4e\xfc\xbc\x4a\x4f\xc4\x18\x6c" + + "\x09\xec\x36\xfd\xf7\x35\x3b\x64\x81\xf7\xb4\x88\x8c\xbc\x83\xbf\xee\x56\xff\x5c\xdd\x5f\x5f\x8e\xc9\x02\x21\x17" + + "\xb4\x77\x8b\xb2\xf0\x5c\xef\x49\x22\x67\x11\xf8\x01\x5b\xfa\xcf\xe1\x96\xe7\x31\xce\x63\x3e\x97\xa5\xab\x31\x0a" + + "\xe7\x8a\x9b\x98\x38\x58\xf7\xdc\xd2\xa0\xeb\x44\x5f\xd4\x75\x9d\xb1\x7b\x71\xd2\xd7\xb2\x4e\x2c\x67\xfe\x08\xca" + + "\x4c\x13\xda\x21\xc7\xa5\x56\x2e\xca\x02\x83\xdf\x7d\xa2\x2f\x81\x85\x54\x05\x57\xd6\x6a\x42\x73\xf6\x1f\x6c\x8d" + + "\x1b\x4d\xa3\x40\xdb\x9f\xf1\x8b\xb6\x98\x0a\xf4\x97\x6d\xbc\x58\xad\x49\x5d\x1d\x6f\x6c\x8b\x6c\x46\x10\x53\xef" + + "\xec\x5c\x15\xe3\xc8\xfd\xb8\x55\x76\xc9\xbb\x4c\x09\xe3\xd6\x14\xbb\x4e\xe3\xf1\x86\x6a\x6e\x51\xbb\x6a\xa0\x2b" + + "\xce\x97\x31\x1f\x13\xc9\xd5\x99\x59\x5b\xa3\x38\x0a\xc0\x65\xce\x2d\x3f\x91\xfa\x10\xda\x4d\x14\xe4\xb9\x50\x8b" + + "\x4f\x33\x1f\xbb\xcf\x46\x73\xcb\x7e\xdc\x8d\x90\xa2\x36\xe9\xea\xd6\x38\x2f\xa1\x9e\x9e\x50\x5b\xad\xd1\x93\xa0" + + "\x5e\x2a\x25\xe4\x1c\xbd\x19\x5d\x73\x63\xd0\x07\x99\x64\x05\x13\xf5\x9f\xfb\xa2\xee\x83\x9b\x89\xe0\xf6\x66\xb8" + + "\xda\xd3\x2e\xec\xf5\x15\x45\x93\xb4\xfd\x11\x59\x32\xd0\xab\x8f\x3c\xf7\x8f\x1f\xeb\xa9\x97\x57\x1e\xf9\x24\x34" + + "\xc3\xc5\x8a\x7f\x5a\x1d\xe2\x15\x9d\xc4\x33\x00\xa6\xee\xd4\xe8\x75\xaf\xb3\x9e\x7c\xdb\x91\x79\x89\x6b\xfb\xf8" + + "\x62\xec\xb8\xd9\x65\x15\x77\x68\x9a\xfc\x04\x6d\x5d\x66\x72\x3c\xee\x80\x7a\xed\x51\x7c\x95\x9e\x56\x12\x81\x38" + + "\x7f\x47\xaa\x21\xb9\x8e\xf9\xd1\x7d\x0e\xc6\x8d\xf2\xad\x98\x15\x45\xb2\xb1\x76\xbf\x8e\x4b\xa8\x82\xdf\x47\xf6" + + "\xcb\x1d\x4c\x5f\xfb\x5b\xb7\xf1\x7f\xe5\x68\xec\x87\xaf\x25\x14\x1b\x56\xc3\x84\xe7\x57\xb8\x61\x35\x65\x62\xc3" + + "\x6a\x85\x4f\xf9\x46\xda\x4f\x51\xe8\xf6\x53\x14\xba\xfd\x8a\x33\xbe\x5c\x27\x84\x6a\x6a\xaf\x58\x7d\xb4\x9c\xed" + + "\xbb\x53\xb7\xbd\xbc\xe3\x3d\x76\x61\xa3\xb9\xfe\x8d\x8e\xf9\xa2\x1d\x2f\xa2\x20\x3a\x5f\xca\xb6\xd5\x9f\x3f\xdd" + + "\xe5\x4b\x88\x14\x09\xc6\xc5\xb1\x26\x39\x8c\x5e\x4d\xdc\xc3\x33\xa7\x17\x34\x6e\x4b\x32\x0b\x3c\xd2\x66\x19\xfc" + + "\xee\x67\xa3\xba\xbe\xeb\x6c\x17\x76\xd6\xb1\x9f\x21\xac\x34\xf7\x8f\xec\x7d\xee\x7c\x2e\xff\x0d\x00\x00\xff\xff" + + "\xd5\x4d\x39\xf2\x60\x09\x00\x00") func bindataSchemagqlBytes() ([]byte, error) { return bindataRead( @@ -171,10 +171,10 @@ func bindataSchemagql() (*asset, error) { info := bindataFileInfo{ name: "schema.gql", - size: 2344, + size: 2400, md5checksum: "", mode: os.FileMode(420), - modTime: time.Unix(1556718973, 0), + modTime: time.Unix(1557448839, 0), } a := &asset{bytes: bytes, info: info} diff --git a/exp/ticker/internal/gql/static/schema.gql b/exp/ticker/internal/gql/static/schema.gql index 86a96ba85e..9b4257db76 100644 --- a/exp/ticker/internal/gql/static/schema.gql +++ b/exp/ticker/internal/gql/static/schema.gql @@ -75,6 +75,7 @@ type Market { close: Float! intervalStart: Time! firstLedgerCloseTime: Time! + lastLedgerCloseTime: Time! orderbookStats: OrderbookStats! } @@ -90,6 +91,7 @@ type AggregatedMarket { close: Float! intervalStart: Time! firstLedgerCloseTime: Time! + lastLedgerCloseTime: Time! orderbookStats: OrderbookStats! } diff --git a/exp/ticker/internal/tickerdb/main.go b/exp/ticker/internal/tickerdb/main.go index 1b2a6569e2..237de6b49b 100644 --- a/exp/ticker/internal/tickerdb/main.go +++ b/exp/ticker/internal/tickerdb/main.go @@ -156,6 +156,7 @@ type PartialMarket struct { LowestAsk float64 `db:"lowest_ask"` IntervalStart time.Time `db:"interval_start"` FirstLedgerCloseTime time.Time `db:"first_ledger_close_time"` + LastLedgerCloseTime time.Time `db:"last_ledger_close_time"` } // CreateSession returns a new TickerSession that connects to the given db settings diff --git a/exp/ticker/internal/tickerdb/queries_market.go b/exp/ticker/internal/tickerdb/queries_market.go index 420eff76b0..ca0c5812e9 100644 --- a/exp/ticker/internal/tickerdb/queries_market.go +++ b/exp/ticker/internal/tickerdb/queries_market.go @@ -204,6 +204,7 @@ SELECT ((array_agg(t.price ORDER BY t.ledger_close_time DESC))[1] - (array_agg(t.price ORDER BY t.ledger_close_time ASC))[1]) AS price_change, (now() - interval '__NUMHOURS__ hours') AS interval_start, min(t.ledger_close_time) AS first_ledger_close_time, + max(t.ledger_close_time) AS last_ledger_close_time, COALESCE((array_agg(os.num_bids))[1], 0) AS num_bids, COALESCE((array_agg(os.bid_volume))[1], 0.0) AS bid_volume, COALESCE((array_agg(os.highest_bid))[1], 0.0) AS highest_bid, @@ -231,6 +232,7 @@ SELECT t1.price_change, t1.interval_start, t1.first_ledger_close_time, + t1.last_ledger_close_time, COALESCE(aob.base_asset_code, '') as base_asset_code, COALESCE(aob.counter_asset_code, '') as counter_asset_code, COALESCE(aob.num_bids, 0) AS num_bids, @@ -251,7 +253,8 @@ FROM ( (array_agg(t.price ORDER BY t.ledger_close_time DESC))[1] AS last_price, ((array_agg(t.price ORDER BY t.ledger_close_time DESC))[1] - (array_agg(t.price ORDER BY t.ledger_close_time ASC))[1]) AS price_change, (now() - interval '__NUMHOURS__ hours') AS interval_start, - min(t.ledger_close_time) AS first_ledger_close_time + min(t.ledger_close_time) AS first_ledger_close_time, + max(t.ledger_close_time) AS last_ledger_close_time FROM trades AS t LEFT JOIN orderbook_stats AS os ON t.base_asset_id = os.base_asset_id AND t.counter_asset_id = os.counter_asset_id JOIN assets AS bAsset ON t.base_asset_id = bAsset.id diff --git a/exp/ticker/internal/tickerdb/queries_market_test.go b/exp/ticker/internal/tickerdb/queries_market_test.go index 7d3ee3956b..625d189bb3 100644 --- a/exp/ticker/internal/tickerdb/queries_market_test.go +++ b/exp/ticker/internal/tickerdb/queries_market_test.go @@ -558,6 +558,11 @@ func TestRetrievePartialMarkets(t *testing.T) { oneHourAgo.Local().Truncate(time.Millisecond), btceth1Mkt.FirstLedgerCloseTime.Local().Truncate(time.Millisecond), ) + assert.Equal( + t, + tenMinutesAgo.Local().Truncate(time.Millisecond), + btceth1Mkt.LastLedgerCloseTime.Local().Truncate(time.Millisecond), + ) assert.Equal(t, 24.0, btceth2Mkt.BaseVolume) assert.Equal(t, 26.0, btceth2Mkt.CounterVolume) @@ -572,6 +577,11 @@ func TestRetrievePartialMarkets(t *testing.T) { now.Local().Truncate(time.Millisecond), btceth2Mkt.FirstLedgerCloseTime.Local().Truncate(time.Millisecond), ) + assert.Equal( + t, + now.Local().Truncate(time.Millisecond), + btceth2Mkt.FirstLedgerCloseTime.Local().Truncate(time.Millisecond), + ) // Analyzing non-aggregated orderbook data assert.Equal(t, 15, btceth1Mkt.NumBids) @@ -608,6 +618,11 @@ func TestRetrievePartialMarkets(t *testing.T) { oneHourAgo.Local().Truncate(time.Millisecond), partialAggMkt.FirstLedgerCloseTime.Local().Truncate(time.Millisecond), ) + assert.Equal( + t, + now.Local().Truncate(time.Millisecond), + partialAggMkt.LastLedgerCloseTime.Local().Truncate(time.Millisecond), + ) // There might be some floating point rounding issues, so this test // needs to be a bit more flexible. Since the change is 0.08, an error