Skip to content
This repository has been archived by the owner on Feb 1, 2024. It is now read-only.

Commit

Permalink
new price feed: last trade price (closes #333) (#334)
Browse files Browse the repository at this point in the history
* 1 - add lastPrice to api.Ticker and to CCXT

* 2 - add last price to tickerAPI of krakenExchange.go

* 3 - log lastTradePrice in exchangeFeed.go

* 4 - add support for "last" price modifier in exchangeFeed and sample config files

* 5 - add note in LIST_OF_HACKS for backward compatibility in defaulting to "mid" price in exchangeFeed

* 6 - move validation check on modifier input to exchange factory method

* 7 - rename GetMidPrice() -> GetFeedPairPrice() in FeedPair
  • Loading branch information
nikhilsaraf authored Jan 6, 2020
1 parent b6eb041 commit afb5628
Show file tree
Hide file tree
Showing 13 changed files with 100 additions and 52 deletions.
1 change: 1 addition & 0 deletions LIST_OF_HACKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
Incomplete list of hacks in the codebase that should be fixed before upgrading to v2.0 which will change the API to Kelp in some way

- LOH-1 - support backward-compatible case of not having any pre-specified function
- LOH-2 - support backward-compatible case of defaulting to "mid" price when left unspecified

## Workarounds

Expand Down
5 changes: 3 additions & 2 deletions api/exchange.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ type Account interface {

// Ticker encapsulates all the data for a given Trading Pair
type Ticker struct {
AskPrice *model.Number
BidPrice *model.Number
AskPrice *model.Number
BidPrice *model.Number
LastPrice *model.Number
}

// TradesResult is the result of a GetTrades call
Expand Down
11 changes: 6 additions & 5 deletions api/priceFeed.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ type PriceFeed interface {
GetPrice() (float64, error)
}

// TODO this should be structured as a specific impl. of the PriceFeed interface
// FeedPair is the struct representing a price feed for a trading pair
type FeedPair struct {
FeedA PriceFeed
FeedB PriceFeed
}

// GetMidPrice fetches the mid price from this feed pair
func (p *FeedPair) GetMidPrice() (float64, error) {
// GetFeedPairPrice fetches the price by dividing FeedA by FeedB
func (p *FeedPair) GetFeedPairPrice() (float64, error) {
pA, err := p.FeedA.GetPrice()
if err != nil {
return 0, err
Expand All @@ -26,7 +27,7 @@ func (p *FeedPair) GetMidPrice() (float64, error) {
return 0, err
}

midPrice := pA / pB
log.Printf("feedPair prices: feedA=%.7f, feedB=%.7f; midPrice=%.7f\n", pA, pB, midPrice)
return midPrice, nil
price := pA / pB
log.Printf("feedPair prices: feedA=%.8f, feedB=%.8f; price=%.8f\n", pA, pB, price)
return price, nil
}
6 changes: 3 additions & 3 deletions examples/configs/trader/sample_buysell.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ DATA_TYPE_A="exchange"
# this code can be retrieved from the exchange's website or from the ccxt manual for ccxt-based exchanges.
# modifier:
# this is a modifier that can be included only for feed type "exchange".
# a modifier allows you to fetch the "mid" price, "ask" price, or "bid" price for now.
# if left unspecified then this is defaulted to "mid" for backwards compatibility (until v2.0 is released)
# a modifier allows you to fetch the "mid" price, "ask" price, "bid" price, or "last" price for now.
# if left unspecified then this is defaulted to "mid" for backwards compatibility (until v2.0 is released) (LOH-2)
# uncomment below to use binance, poloniex, or bittrex as your price feed. You will need to set up CCXT to use this, see the "Using CCXT" section in the README for details.
# be careful about using USD vs. USDT since some exchanges support only one, or both, or in some cases neither.
#DATA_FEED_A_URL="ccxt-kraken/XLM/USD/mid"
#DATA_FEED_A_URL="ccxt-kraken/XLM/USD/last"
#DATA_FEED_A_URL="ccxt-binance/XLM/USDT/ask"
#DATA_FEED_A_URL="ccxt-poloniex/XLM/USDT/bid"
# bittrex does not have an XLM/USD market so this config lists XLM/BTC instead; you should NOT use this when trying to price an asset based on the XLM/USD price (unless you know what you are doing).
Expand Down
6 changes: 3 additions & 3 deletions examples/configs/trader/sample_sell.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ DATA_TYPE_A="exchange"
# this code can be retrieved from the exchange's website or from the ccxt manual for ccxt-based exchanges.
# modifier:
# this is a modifier that can be included only for feed type "exchange".
# a modifier allows you to fetch the "mid" price, "ask" price, or "bid" price for now.
# if left unspecified then this is defaulted to "mid" for backwards compatibility (until v2.0 is released)
# a modifier allows you to fetch the "mid" price, "ask" price, "bid" price, or "last" price for now.
# if left unspecified then this is defaulted to "mid" for backwards compatibility (until v2.0 is released) (LOH-2)
# uncomment below to use binance, poloniex, or bittrex as your price feed. You will need to set up CCXT to use this, see the "Using CCXT" section in the README for details.
# be careful about using USD vs. USDT since some exchanges support only one, or both, or in some cases neither.
#DATA_FEED_A_URL="ccxt-kraken/XLM/USD/mid"
#DATA_FEED_A_URL="ccxt-kraken/XLM/USD/last"
#DATA_FEED_A_URL="ccxt-binance/XLM/USDT/ask"
#DATA_FEED_A_URL="ccxt-poloniex/XLM/USDT/bid"
# bittrex does not have an XLM/USD market so this config lists XLM/BTC instead; you should NOT use this when trying to price an asset based on the XLM/USD price (unless you know what you are doing).
Expand Down
20 changes: 15 additions & 5 deletions plugins/ccxtExchange.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,22 @@ func (c ccxtExchange) GetTickerPrice(pairs []model.TradingPair) (map[model.Tradi

askPrice, e := utils.CheckFetchFloat(tickerMap, "ask")
if e != nil {
return nil, fmt.Errorf("unable to correctly fetch value from tickerMap: %s", e)
return nil, fmt.Errorf("unable to correctly fetch 'ask' value from tickerMap: %s", e)
}
bidPrice, e := utils.CheckFetchFloat(tickerMap, "bid")
if e != nil {
return nil, fmt.Errorf("unable to correctly fetch value from tickerMap: %s", e)
return nil, fmt.Errorf("unable to correctly fetch 'bid' value from tickerMap: %s", e)
}
lastPrice, e := utils.CheckFetchFloat(tickerMap, "last")
if e != nil {
return nil, fmt.Errorf("unable to correctly fetch 'last' value from tickerMap: %s", e)
}

pricePrecision := c.GetOrderConstraints(&p).PricePrecision
priceResult[p] = api.Ticker{
AskPrice: model.NumberFromFloat(askPrice, c.GetOrderConstraints(&p).PricePrecision),
BidPrice: model.NumberFromFloat(bidPrice, c.GetOrderConstraints(&p).PricePrecision),
AskPrice: model.NumberFromFloat(askPrice, pricePrecision),
BidPrice: model.NumberFromFloat(bidPrice, pricePrecision),
LastPrice: model.NumberFromFloat(lastPrice, pricePrecision),
}
}

Expand All @@ -114,7 +120,11 @@ func (c ccxtExchange) GetOrderConstraints(pair *model.TradingPair) *model.OrderC
if ccxtMarket == nil {
panic(fmt.Errorf("CCXT does not have precision and limit data for the passed in market: %s", pairString))
}
oc := model.MakeOrderConstraintsWithCost(ccxtMarket.Precision.Price, ccxtMarket.Precision.Amount, ccxtMarket.Limits.Amount.Min, ccxtMarket.Limits.Cost.Min)
volumePrecision := ccxtMarket.Precision.Amount
if volumePrecision == 0 {
volumePrecision = ccxtMarket.Precision.Price
}
oc := model.MakeOrderConstraintsWithCost(ccxtMarket.Precision.Price, volumePrecision, ccxtMarket.Limits.Amount.Min, ccxtMarket.Limits.Cost.Min)

return c.ocOverridesHandler.Apply(pair, oc)
}
Expand Down
46 changes: 29 additions & 17 deletions plugins/ccxtExchange_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package plugins
import (
"fmt"
"log"
"math"
"strconv"
"testing"
"time"
Expand All @@ -12,16 +13,22 @@ import (
"github.com/stretchr/testify/assert"
)

var supportedExchanges = []string{"binance"}
var supportedExchanges = []string{"binance", "kraken"}
var emptyAPIKey = api.ExchangeAPIKey{}
var emptyParams = api.ExchangeParam{}
var supportedTradingExchanges = map[string]api.ExchangeAPIKey{
"binance": {},
}

var testOrderConstraints = map[model.TradingPair]model.OrderConstraints{
*model.MakeTradingPair(model.XLM, model.USDT): *model.MakeOrderConstraints(4, 5, 0.1),
*model.MakeTradingPair(model.XLM, model.BTC): *model.MakeOrderConstraints(8, 4, 1.0),
var testOrderConstraints = map[string]map[model.TradingPair]model.OrderConstraints{
"binance": map[model.TradingPair]model.OrderConstraints{
*model.MakeTradingPair(model.XLM, model.USDT): *model.MakeOrderConstraints(4, 5, 0.1),
*model.MakeTradingPair(model.XLM, model.BTC): *model.MakeOrderConstraints(8, 4, 1.0),
},
"kraken": map[model.TradingPair]model.OrderConstraints{
*model.MakeTradingPair(model.XLM, model.USD): *model.MakeOrderConstraints(6, 8, 30.0),
*model.MakeTradingPair(model.XLM, model.BTC): *model.MakeOrderConstraints(8, 8, 30.0),
},
}

func TestGetTickerPrice_Ccxt(t *testing.T) {
Expand All @@ -31,7 +38,7 @@ func TestGetTickerPrice_Ccxt(t *testing.T) {

for _, exchangeName := range supportedExchanges {
t.Run(exchangeName, func(t *testing.T) {
testCcxtExchange, e := makeCcxtExchange(exchangeName, testOrderConstraints, []api.ExchangeAPIKey{emptyAPIKey}, []api.ExchangeParam{emptyParams}, []api.ExchangeHeader{}, false)
testCcxtExchange, e := makeCcxtExchange(exchangeName, testOrderConstraints[exchangeName], []api.ExchangeAPIKey{emptyAPIKey}, []api.ExchangeParam{emptyParams}, []api.ExchangeHeader{}, false)
if !assert.NoError(t, e) {
return
}
Expand All @@ -47,6 +54,9 @@ func TestGetTickerPrice_Ccxt(t *testing.T) {

ticker := m[pair]
assert.True(t, ticker.AskPrice.AsFloat() < 1, ticker.AskPrice.AsString())
assert.True(t, ticker.BidPrice.AsFloat() < 1, ticker.BidPrice.AsString())
assert.True(t, ticker.BidPrice.AsFloat() < ticker.AskPrice.AsFloat(), fmt.Sprintf("bid price (%s) should be less than ask price (%s)", ticker.BidPrice.AsString(), ticker.AskPrice.AsString()))
assert.True(t, ticker.LastPrice.AsFloat() < 1, ticker.LastPrice.AsString())
})
}
}
Expand All @@ -58,7 +68,7 @@ func TestGetOrderBook_Ccxt(t *testing.T) {

for _, exchangeName := range supportedExchanges {
t.Run(exchangeName, func(t *testing.T) {
testCcxtExchange, e := makeCcxtExchange(exchangeName, testOrderConstraints, []api.ExchangeAPIKey{emptyAPIKey}, []api.ExchangeParam{emptyParams}, []api.ExchangeHeader{}, false)
testCcxtExchange, e := makeCcxtExchange(exchangeName, testOrderConstraints[exchangeName], []api.ExchangeAPIKey{emptyAPIKey}, []api.ExchangeParam{emptyParams}, []api.ExchangeHeader{}, false)
if !assert.NoError(t, e) {
return
}
Expand Down Expand Up @@ -91,7 +101,7 @@ func TestGetTrades_Ccxt(t *testing.T) {

for _, exchangeName := range supportedExchanges {
t.Run(exchangeName, func(t *testing.T) {
testCcxtExchange, e := makeCcxtExchange(exchangeName, testOrderConstraints, []api.ExchangeAPIKey{emptyAPIKey}, []api.ExchangeParam{}, []api.ExchangeHeader{}, false)
testCcxtExchange, e := makeCcxtExchange(exchangeName, testOrderConstraints[exchangeName], []api.ExchangeAPIKey{emptyAPIKey}, []api.ExchangeParam{}, []api.ExchangeHeader{}, false)
if !assert.NoError(t, e) {
return
}
Expand All @@ -117,7 +127,7 @@ func TestGetTradeHistory_Ccxt(t *testing.T) {

for exchangeName, apiKey := range supportedTradingExchanges {
t.Run(exchangeName, func(t *testing.T) {
testCcxtExchange, e := makeCcxtExchange(exchangeName, testOrderConstraints, []api.ExchangeAPIKey{apiKey}, []api.ExchangeParam{emptyParams}, []api.ExchangeHeader{}, false)
testCcxtExchange, e := makeCcxtExchange(exchangeName, testOrderConstraints[exchangeName], []api.ExchangeAPIKey{apiKey}, []api.ExchangeParam{emptyParams}, []api.ExchangeHeader{}, false)
if !assert.NoError(t, e) {
return
}
Expand All @@ -144,10 +154,10 @@ func validateTrades(t *testing.T, pair model.TradingPair, trades []model.Trade)
if !assert.Equal(t, &pair, trade.Pair) {
return
}
if !assert.True(t, trade.Price.AsFloat() > 0, fmt.Sprintf("%.7f", trade.Price.AsFloat())) {
if !assert.True(t, trade.Price.AsFloat() > 0, trade.Price.AsString()) {
return
}
if !assert.True(t, trade.Volume.AsFloat() > 0, fmt.Sprintf("%.7f", trade.Volume.AsFloat())) {
if !assert.True(t, trade.Volume.AsFloat() > 0, trade.Volume.AsString()) {
return
}
if !assert.Equal(t, trade.OrderType, model.OrderTypeLimit) {
Expand All @@ -169,7 +179,9 @@ func validateTrades(t *testing.T, pair model.TradingPair, trades []model.Trade)
assert.Fail(t, "trade.OrderAction should be either OrderActionBuy or OrderActionSell: %v", trade.OrderAction)
return
}
if !assert.True(t, trade.Cost.AsFloat() > 0, fmt.Sprintf("(price) %s x (volume) %s = (cost) %s", trade.Price.AsString(), trade.Volume.AsString(), trade.Cost.AsString())) {
minPrecision := math.Min(float64(trade.Price.Precision()), float64(trade.Volume.Precision()))
nonZeroCalculatedCost := trade.Price.AsFloat()*trade.Volume.AsFloat() > math.Pow(10, -minPrecision)
if nonZeroCalculatedCost && !assert.True(t, trade.Cost.AsFloat() > 0, fmt.Sprintf("(price) %s x (volume) %s = (cost) %s", trade.Price.AsString(), trade.Volume.AsString(), trade.Cost.AsString())) {
return
}
}
Expand All @@ -178,7 +190,7 @@ func validateTrades(t *testing.T, pair model.TradingPair, trades []model.Trade)
func TestGetLatestTradeCursor_Ccxt(t *testing.T) {
for exchangeName, apiKey := range supportedTradingExchanges {
t.Run(exchangeName, func(t *testing.T) {
testCcxtExchange, e := makeCcxtExchange(exchangeName, testOrderConstraints, []api.ExchangeAPIKey{apiKey}, []api.ExchangeParam{emptyParams}, []api.ExchangeHeader{}, false)
testCcxtExchange, e := makeCcxtExchange(exchangeName, testOrderConstraints[exchangeName], []api.ExchangeAPIKey{apiKey}, []api.ExchangeParam{emptyParams}, []api.ExchangeHeader{}, false)
if !assert.NoError(t, e) {
return
}
Expand Down Expand Up @@ -217,7 +229,7 @@ func TestGetAccountBalances_Ccxt(t *testing.T) {

for exchangeName, apiKey := range supportedTradingExchanges {
t.Run(exchangeName, func(t *testing.T) {
testCcxtExchange, e := makeCcxtExchange(exchangeName, testOrderConstraints, []api.ExchangeAPIKey{apiKey}, []api.ExchangeParam{emptyParams}, []api.ExchangeHeader{}, false)
testCcxtExchange, e := makeCcxtExchange(exchangeName, testOrderConstraints[exchangeName], []api.ExchangeAPIKey{apiKey}, []api.ExchangeParam{emptyParams}, []api.ExchangeHeader{}, false)
if !assert.NoError(t, e) {
return
}
Expand Down Expand Up @@ -262,7 +274,7 @@ func TestGetOpenOrders_Ccxt(t *testing.T) {
for exchangeName, apiKey := range supportedTradingExchanges {
for _, pair := range tradingPairs {
t.Run(exchangeName, func(t *testing.T) {
testCcxtExchange, e := makeCcxtExchange(exchangeName, testOrderConstraints, []api.ExchangeAPIKey{apiKey}, []api.ExchangeParam{emptyParams}, []api.ExchangeHeader{}, false)
testCcxtExchange, e := makeCcxtExchange(exchangeName, testOrderConstraints[exchangeName], []api.ExchangeAPIKey{apiKey}, []api.ExchangeParam{emptyParams}, []api.ExchangeHeader{}, false)
if !assert.NoError(t, e) {
return
}
Expand Down Expand Up @@ -377,7 +389,7 @@ func TestAddOrder_Ccxt(t *testing.T) {
},
} {
t.Run(exchangeName, func(t *testing.T) {
testCcxtExchange, e := makeCcxtExchange(exchangeName, testOrderConstraints, []api.ExchangeAPIKey{apiKey}, []api.ExchangeParam{emptyParams}, []api.ExchangeHeader{}, false)
testCcxtExchange, e := makeCcxtExchange(exchangeName, testOrderConstraints[exchangeName], []api.ExchangeAPIKey{apiKey}, []api.ExchangeParam{emptyParams}, []api.ExchangeHeader{}, false)
if !assert.NoError(t, e) {
return
}
Expand Down Expand Up @@ -427,7 +439,7 @@ func TestCancelOrder_Ccxt(t *testing.T) {
},
} {
t.Run(exchangeName, func(t *testing.T) {
testCcxtExchange, e := makeCcxtExchange(exchangeName, testOrderConstraints, []api.ExchangeAPIKey{apiKey}, []api.ExchangeParam{emptyParams}, []api.ExchangeHeader{}, false)
testCcxtExchange, e := makeCcxtExchange(exchangeName, testOrderConstraints[exchangeName], []api.ExchangeAPIKey{apiKey}, []api.ExchangeParam{emptyParams}, []api.ExchangeHeader{}, false)
if !assert.NoError(t, e) {
return
}
Expand Down Expand Up @@ -473,7 +485,7 @@ func TestGetOrderConstraints_Ccxt_Precision(t *testing.T) {
exchangeName: "binance",
pair: &model.TradingPair{Base: model.XLM, Quote: model.BTC},
wantPricePrecision: 8,
wantVolPrecision: 0,
wantVolPrecision: 8,
},
}

Expand Down
32 changes: 24 additions & 8 deletions plugins/exchangeFeed.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,17 @@ type exchangeFeed struct {
// ensure that it implements PriceFeed
var _ api.PriceFeed = &exchangeFeed{}

func newExchangeFeed(name string, tickerAPI *api.TickerAPI, pair *model.TradingPair, modifier string) *exchangeFeed {
func newExchangeFeed(name string, tickerAPI *api.TickerAPI, pair *model.TradingPair, modifier string) (*exchangeFeed, error) {
if modifier != "mid" && modifier != "ask" && modifier != "bid" && modifier != "last" {
return nil, fmt.Errorf("unsupported modifier '%s' on exchange type URL", modifier)
}

return &exchangeFeed{
name: name,
tickerAPI: tickerAPI,
pairs: []model.TradingPair{*pair},
modifier: modifier,
}
}, nil
}

// GetPrice impl
Expand All @@ -41,15 +45,27 @@ func (f *exchangeFeed) GetPrice() (float64, error) {
return 0, fmt.Errorf("could not get price for trading pair: %s", f.pairs[0].String())
}

midPrice := (p.BidPrice.AsFloat() + p.AskPrice.AsFloat()) / 2
var price float64
midPrice := p.BidPrice.Add(*p.AskPrice).Scale(0.5)
var price *model.Number
if f.modifier == "ask" {
price = p.AskPrice.AsFloat()
price = p.AskPrice
} else if f.modifier == "bid" {
price = p.BidPrice.AsFloat()
price = p.BidPrice
} else if f.modifier == "last" {
price = p.LastPrice
} else {
// LOH-2 - support backward-compatible case of defaulting to "mid" price when left unspecified
price = midPrice
}
log.Printf("(modifier: %s) price from exchange feed (%s): bidPrice=%.7f, askPrice=%.7f, midPrice=%.7f; price=%.7f", f.modifier, f.name, p.BidPrice.AsFloat(), p.AskPrice.AsFloat(), midPrice, price)
return price, nil

log.Printf("(modifier: %s) price from exchange feed (%s): bidPrice=%s, askPrice=%s, midPrice=%s, lastTradePrice=%s; price=%s",
f.modifier,
f.name,
p.BidPrice.AsString(),
p.AskPrice.AsString(),
midPrice.AsString(),
p.LastPrice.AsString(),
price.AsString(),
)
return price.AsFloat(), nil
}
5 changes: 3 additions & 2 deletions plugins/krakenExchange.go
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,9 @@ func (k *krakenExchange) GetTickerPrice(pairs []model.TradingPair) (map[model.Tr
orderConstraints := k.GetOrderConstraints(&p)
pairTickerInfo := resp.GetPairTickerInfo(pairsMap[p])
priceResult[p] = api.Ticker{
AskPrice: model.MustNumberFromString(pairTickerInfo.Ask[0], orderConstraints.PricePrecision),
BidPrice: model.MustNumberFromString(pairTickerInfo.Bid[0], orderConstraints.PricePrecision),
AskPrice: model.MustNumberFromString(pairTickerInfo.Ask[0], orderConstraints.PricePrecision),
BidPrice: model.MustNumberFromString(pairTickerInfo.Bid[0], orderConstraints.PricePrecision),
LastPrice: model.MustNumberFromString(pairTickerInfo.Close[0], orderConstraints.PricePrecision),
}
}

Expand Down
8 changes: 7 additions & 1 deletion plugins/krakenExchange_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,20 @@ func TestGetTickerPrice(t *testing.T) {
assert.Equal(t, 1, len(m))

ticker := m[pair]
fmt.Printf("ticker price: bid=%.8f, ask=%.8f\n", ticker.BidPrice.AsFloat(), ticker.AskPrice.AsFloat())
fmt.Printf("ticker price: bid=%s, ask=%s, last=%s\n", ticker.BidPrice.AsString(), ticker.AskPrice.AsString(), ticker.LastPrice.AsString())

if !assert.True(t, ticker.AskPrice.AsFloat() < 1, ticker.AskPrice.AsString()) {
return
}
if !assert.True(t, ticker.BidPrice.AsFloat() < 1, ticker.BidPrice.AsString()) {
return
}
if !assert.True(t, ticker.BidPrice.AsFloat() < ticker.AskPrice.AsFloat(), fmt.Sprintf("bid price (%s) should be less than ask price (%s)", ticker.BidPrice.AsString(), ticker.AskPrice.AsString())) {
return
}
if !assert.True(t, ticker.LastPrice.AsFloat() < 1, ticker.LastPrice.AsString()) {
return
}
}

func TestGetAccountBalances(t *testing.T) {
Expand Down
7 changes: 2 additions & 5 deletions plugins/priceFeed.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,10 @@ func MakePriceFeed(feedType string, url string) (api.PriceFeed, error) {
return nil, fmt.Errorf("invalid format of exchange type URL, needs either 3 or 4 parts after splitting URL by '/', has %d: %s", len(urlParts), url)
}

// default to "mid" for backwards compatibility
// LOH-2 - support backward-compatible case of defaulting to "mid" price when left unspecified
exchangeModifier := "mid"
if len(urlParts) == 4 {
exchangeModifier = urlParts[3]
if exchangeModifier != "mid" && exchangeModifier != "ask" && exchangeModifier != "bid" {
return nil, fmt.Errorf("unsupported exchange modifier '%s' on exchange type URL", exchangeModifier)
}
}

exchange, e := MakeExchange(urlParts[0], true)
Expand All @@ -75,7 +72,7 @@ func MakePriceFeed(feedType string, url string) (api.PriceFeed, error) {
Quote: quoteAsset,
}
tickerAPI := api.TickerAPI(exchange)
return newExchangeFeed(url, &tickerAPI, &tradingPair, exchangeModifier), nil
return newExchangeFeed(url, &tickerAPI, &tradingPair, exchangeModifier)
case "sdex":
sdex, e := makeSDEXFeed(url)
if e != nil {
Expand Down
2 changes: 1 addition & 1 deletion plugins/staticSpreadLevelProvider.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func makeStaticSpreadLevelProvider(staticLevels []StaticLevel, amountOfBase floa

// GetLevels impl.
func (p *staticSpreadLevelProvider) GetLevels(maxAssetBase float64, maxAssetQuote float64) ([]api.Level, error) {
midPrice, e := p.pf.GetMidPrice()
midPrice, e := p.pf.GetFeedPairPrice()
if e != nil {
return nil, fmt.Errorf("mid price couldn't be loaded: %s", e)
}
Expand Down
Loading

0 comments on commit afb5628

Please sign in to comment.