Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

exp/ticker: Orderbook data support #1193

Merged
merged 28 commits into from
May 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
5b37560
exp/ticker: update partial market query to also output base/counter a…
accordeiro Apr 24, 2019
6e1346c
exp/ticker: add functions to scrape orderbook data
accordeiro Apr 24, 2019
5df5153
exp/ticker: update orderbookstats param names to match market standards
accordeiro Apr 25, 2019
44463a9
exp/ticker: create orderbookstats database model and migrations
accordeiro Apr 25, 2019
3d0e4d2
exp/ticker: consolidate upsert logic and implement orderbookstats upsert
accordeiro Apr 25, 2019
bc5ff85
exp/ticker: create CLI command to ingest orderbooks
accordeiro Apr 25, 2019
1eda6dc
Merge branch 'master' into exp/ticker/orderbook
accordeiro Apr 25, 2019
fd0250a
exp/ticker: update horizon SDK path
accordeiro Apr 25, 2019
c3a1a78
exp/ticker: add orderbook stats to market.json generator
accordeiro Apr 25, 2019
5215bdb
exp/ticker: add separate query to retrieve relevant markets
accordeiro Apr 25, 2019
b25240e
exp/ticker: add orderbook stats to graphql interface
accordeiro Apr 25, 2019
d5fce2a
exp/ticker: add Docker support for orderbook ingestion
accordeiro Apr 25, 2019
aa513d9
exp/ticker: fix partial aggregated market query + add tests
accordeiro Apr 26, 2019
22a01aa
exp/ticker: fix globall aggregated market query + add tests
accordeiro Apr 26, 2019
c90b270
exp/ticker: update ticker binary link and fix crontab comment
accordeiro Apr 26, 2019
3bc5ad4
exp/ticker: fix issue that would enable inf values to be stored in db
accordeiro Apr 26, 2019
f311ee4
exp/ticker: ensure only store valid orderbook entries are stored
accordeiro Apr 26, 2019
9185656
exp/ticker: format gql/static/bindata.go to prevent CI errors
accordeiro Apr 26, 2019
3f7c748
Merge branch 'master' into exp/ticker/orderbook
accordeiro Apr 29, 2019
e534072
exp/ticker: add updated bindata with pg 9.5-compatible migrations
accordeiro Apr 29, 2019
4d24aa5
exp/ticker: ensure markets with 0 orderbook entries can be handled by…
accordeiro Apr 29, 2019
9025afb
exp/ticker: remove unnecessary commas from graphql schema
accordeiro May 1, 2019
878d795
exp/ticker: consolidate bid and ask positions on field names
accordeiro May 1, 2019
a1e9383
exp/ticker: simplify logic for creating orderbook requests
accordeiro May 1, 2019
fbdff21
exp/ticker: fix how bid and ask volumes are calculated
accordeiro May 1, 2019
f290fc8
exp/ticker: allow negative spread values
accordeiro May 1, 2019
37beb42
exp/ticker: fix close_time fallback on markets query
accordeiro May 1, 2019
361f5e1
exp/ticker: add page size limit to orderbook requests
accordeiro May 2, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion exp/ticker/cmd/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ var cmdGenerateAssetData = &cobra.Command{
Logger.Infof("Starting asset data generation, outputting to: %s\n", AssetsOutFile)
err = ticker.GenerateAssetsFile(&session, Logger, AssetsOutFile)
if err != nil {
Logger.Fatal("could not generate market data:", err)
Logger.Fatal("could not generate asset data:", err)
}
},
}
24 changes: 24 additions & 0 deletions exp/ticker/cmd/ingest.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ func init() {
rootCmd.AddCommand(cmdIngest)
cmdIngest.AddCommand(cmdIngestAssets)
cmdIngest.AddCommand(cmdIngestTrades)
cmdIngest.AddCommand(cmdIngestOrderbooks)

cmdIngestTrades.Flags().BoolVar(
&ShouldStream,
Expand Down Expand Up @@ -96,3 +97,26 @@ var cmdIngestTrades = &cobra.Command{
}
},
}

var cmdIngestOrderbooks = &cobra.Command{
Use: "orderbooks",
Short: "Refreshes the orderbook stats database with new data retrieved from Horizon.",
Run: func(cmd *cobra.Command, args []string) {
Logger.Info("Refreshing the asset database")
dbInfo, err := pq.ParseURL(DatabaseURL)
if err != nil {
Logger.Fatal("could not parse db-url:", err)
}

session, err := tickerdb.CreateSession("postgres", dbInfo)
if err != nil {
Logger.Fatal("could not connect to db:", err)
}
defer session.DB.Close()

err = ticker.RefreshOrderbookEntries(&session, Client, Logger)
if err != nil {
Logger.Fatal("could not refresh error database:", err)
}
},
}
3 changes: 3 additions & 0 deletions exp/ticker/docker/conf/crontab.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
# Refresh the database of assets, hourly:
@hourly /opt/stellar/bin/ticker ingest assets --db-url=postgres://127.0.0.1:5432/ticker > /home/stellar/last-ingest-assets.log 2>&1

# Refresh the database of orderbooks, every 10 minutes:
*/10 * * * * /opt/stellar/bin/ticker ingest orderbooks --db-url=postgres://127.0.0.1:5432/ticker > /home/stellar/last-ingest-orderbooks.log 2>&1

# Backfill the database of trades (including possible new assets), every 6 hours:
0 */6 * * * /opt/stellar/bin/ticker ingest trades --db-url=postgres://127.0.0.1:5432/ticker > /home/stellar/last-ingest-trades.log 2>&1

Expand Down
2 changes: 1 addition & 1 deletion exp/ticker/docker/setup
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ mkdir -p /opt/stellar/www
chown -R stellar:stellar /opt/stellar/www
mkdir -p /opt/stellar/postgresql/data

wget -O ticker.tar.gz https://github.com/accordeiro/ticker-releases/releases/download/v0.4-alpha/ticker.tar.gz
wget -O ticker.tar.gz https://github.com/accordeiro/ticker-releases/releases/download/v0.5.3-alpha/ticker.tar.gz
tar -xvzf ticker.tar.gz
mv ticker /opt/stellar/bin/ticker
chmod +x /opt/stellar/bin/ticker
14 changes: 14 additions & 0 deletions exp/ticker/docker/start
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ function main() {

populate_assets
populate_trades
populate_orderbooks
generate_assets_file
generate_markets_file

Expand Down Expand Up @@ -70,6 +71,19 @@ function populate_trades() {
}


function populate_orderbooks() {
if [ -f $PGHOME/.orderbooks-populated ]; then
echo "ticker: orderbooks already pre-populated"
return 0
fi
echo ""
echo "Populating initial orderbook database"
echo ""
sudo -u stellar $STELLAR_BIN/ticker ingest orderbooks --db-url=$PGURL
touch $PGHOME/.orderbooks-populated
}


function generate_assets_file() {
if [ -f $STELLAR_HOME/www/assets.json ]; then
echo "ticker: assets.json already pre-populated"
Expand Down
10 changes: 10 additions & 0 deletions exp/ticker/internal/actions_market.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ func GenerateMarketSummary(s *tickerdb.TickerSession) (ms MarketSummary, err err

func dbMarketToMarketStats(m tickerdb.Market) MarketStats {
closeTime := utils.TimeToUnixEpoch(m.LastPriceCloseTime)

spread, spreadMidPoint := utils.CalcSpread(m.HighestBid, m.LowestAsk)
return MarketStats{
TradePairName: m.TradePair,
BaseVolume24h: m.BaseVolume24h,
Expand All @@ -77,6 +79,14 @@ func dbMarketToMarketStats(m tickerdb.Market) MarketStats {
Change7d: m.PriceChange7d,
Price: m.LastPrice,
Close: m.LastPrice,
BidCount: m.NumBids,
BidVolume: m.BidVolume,
BidMax: m.HighestBid,
AskCount: m.NumAsks,
AskVolume: m.AskVolume,
AskMin: m.LowestAsk,
Spread: spread,
SpreadMidPoint: spreadMidPoint,
CloseTime: closeTime,
}
}
65 changes: 65 additions & 0 deletions exp/ticker/internal/actions_orderbook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package ticker

import (
"time"

horizonclient "github.com/stellar/go/clients/horizonclient"
"github.com/stellar/go/exp/ticker/internal/scraper"
"github.com/stellar/go/exp/ticker/internal/tickerdb"
"github.com/stellar/go/support/errors"
hlog "github.com/stellar/go/support/log"
)

// RefreshOrderbookEntries updates the orderbook entries for the relevant markets that were active
// in the past 7-day interval
func RefreshOrderbookEntries(s *tickerdb.TickerSession, c *horizonclient.Client, l *hlog.Entry) error {
sc := scraper.ScraperConfig{
Client: c,
Logger: l,
}

// Retrieve relevant markets for the past 7 days (168 hours):
mkts, err := s.Retrieve7DRelevantMarkets()
if err != nil {
return errors.Wrap(err, "could not retrieve partial markets")
}

for _, mkt := range mkts {
ob, err := sc.FetchOrderbookForAssets(
mkt.BaseAssetType,
mkt.BaseAssetCode,
mkt.BaseAssetIssuer,
mkt.CounterAssetType,
mkt.CounterAssetCode,
mkt.CounterAssetIssuer,
)
if err != nil {
l.Error(errors.Wrap(err, "could not fetch orderbook for assets"))
continue
}

dbOS := orderbookStatsToDBOrderbookStats(ob, mkt.BaseAssetID, mkt.CounterAssetID)
err = s.InsertOrUpdateOrderbookStats(&dbOS, []string{"base_asset_id", "counter_asset_id"})
if err != nil {
l.Error(errors.Wrap(err, "could not insert orderbook stats into db"))
}
}

return nil
}

func orderbookStatsToDBOrderbookStats(os scraper.OrderbookStats, bID, cID int32) tickerdb.OrderbookStats {
return tickerdb.OrderbookStats{
BaseAssetID: bID,
CounterAssetID: cID,
NumBids: os.NumBids,
BidVolume: os.BidVolume,
HighestBid: os.HighestBid,
NumAsks: os.NumAsks,
AskVolume: os.AskVolume,
LowestAsk: os.LowestAsk,
Spread: os.Spread,
SpreadMidPoint: os.SpreadMidPoint,
UpdatedAt: time.Now(),
}
}
15 changes: 15 additions & 0 deletions exp/ticker/internal/gql/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type asset struct {
Countries string
Status string
IssuerID int32
OrderbookStats orderbookStats
}

// partialMarket represents the aggregated market data for a
Expand All @@ -58,6 +59,20 @@ type partialMarket struct {
Close float64
IntervalStart graphql.Time
FirstLedgerCloseTime graphql.Time
OrderbookStats orderbookStats
}

// orderbookStats represents the orderbook stats for a
// specific pair of assets (aggregated or not)
type orderbookStats struct {
BidCount BigInt
BidVolume float64
BidMax float64
AskCount BigInt
AskVolume float64
AskMin float64
Spread float64
SpreadMidPoint float64
}

type resolver struct {
Expand Down
14 changes: 14 additions & 0 deletions exp/ticker/internal/gql/resolvers_market.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/graph-gophers/graphql-go"
"github.com/stellar/go/exp/ticker/internal/tickerdb"
"github.com/stellar/go/exp/ticker/internal/utils"
)

// Markets resolves the markets() GraphQL query.
Expand Down Expand Up @@ -83,6 +84,18 @@ func validateNumHoursAgo(n *int32) (int, error) {

// dbMarketToPartialMarket converts a tickerdb.PartialMarket to a *partialMarket
func dbMarketToPartialMarket(dbMarket tickerdb.PartialMarket) *partialMarket {
spread, spreadMidPoint := utils.CalcSpread(dbMarket.HighestBid, dbMarket.LowestAsk)
os := orderbookStats{
BidCount: BigInt(dbMarket.NumBids),
BidVolume: dbMarket.BidVolume,
BidMax: dbMarket.HighestBid,
AskCount: BigInt(dbMarket.NumAsks),
AskVolume: dbMarket.AskVolume,
AskMin: dbMarket.LowestAsk,
Spread: spread,
SpreadMidPoint: spreadMidPoint,
}

return &partialMarket{
TradePair: dbMarket.TradePairName,
BaseAssetCode: dbMarket.BaseAssetCode,
Expand All @@ -99,5 +112,6 @@ func dbMarketToPartialMarket(dbMarket tickerdb.PartialMarket) *partialMarket {
Close: dbMarket.Close,
IntervalStart: graphql.Time{Time: dbMarket.IntervalStart},
FirstLedgerCloseTime: graphql.Time{Time: dbMarket.FirstLedgerCloseTime},
OrderbookStats: os,
}
}
63 changes: 33 additions & 30 deletions exp/ticker/internal/gql/static/bindata.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions exp/ticker/internal/gql/static/schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ type Market {
close: Float!
intervalStart: Time!
firstLedgerCloseTime: Time!
orderbookStats: OrderbookStats!
}

type AggregatedMarket {
Expand All @@ -89,6 +90,18 @@ type AggregatedMarket {
close: Float!
intervalStart: Time!
firstLedgerCloseTime: Time!
orderbookStats: OrderbookStats!
}

type OrderbookStats {
bidCount: BigInt!
bidVolume: Float!
bidMax: Float!
askCount: BigInt!
askVolume: Float!
askMin: Float!
spread: Float!
spreadMidPoint: Float!
}

type Issuer {
Expand Down
8 changes: 8 additions & 0 deletions exp/ticker/internal/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ type MarketStats struct {
Price float64 `json:"price"`
Close float64 `json:"close"`
CloseTime int64 `json:"close_time"`
BidCount int `json:"bid_count"`
BidVolume float64 `json:"bid_volume"`
BidMax float64 `json:"bid_max"`
AskCount int `json:"ask_count"`
AskVolume float64 `json:"ask_volume"`
AskMin float64 `json:"ask_min"`
Spread float64 `json:"spread"`
SpreadMidPoint float64 `json:"spread_mid_point"`
}

// Asset Sumary represents the collection of valid assets.
Expand Down
Loading