-
Notifications
You must be signed in to change notification settings - Fork 263
Add sdex price feed #90
Changes from 10 commits
e11a3a3
84add7e
73e541a
1f16537
18eb7b0
3032a19
189aea4
372ecc3
7239b3b
469bf1f
c4330b5
f76942b
07e72b7
978254a
d4e7cf3
93ecf44
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -94,9 +94,9 @@ func MakeSDEX( | |
threadTracker: threadTracker, | ||
operationalBuffer: operationalBuffer, | ||
operationalBufferNonNativePct: operationalBufferNonNativePct, | ||
simMode: simMode, | ||
pair: pair, | ||
assetMap: assetMap, | ||
simMode: simMode, | ||
pair: pair, | ||
assetMap: assetMap, | ||
} | ||
|
||
log.Printf("Using network passphrase: %s\n", sdex.Network.Passphrase) | ||
|
@@ -813,3 +813,19 @@ func (sdex *SDEX) GetLatestTradeCursor() (interface{}, error) { | |
|
||
return records[0].PT, nil | ||
} | ||
|
||
// GetOrderBook gets the SDEX order book | ||
func (sdex *SDEX) GetOrderBook(pair *model.TradingPair) (orderBook horizon.OrderBookSummary, e error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should conform to the API method described in the previous comments:
this would require transforming orders from horizon's format to the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sample code would be great There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Reidmcc the sample code below converts a single func manageOffer2Order(mob *build.ManageOfferBuilder, baseAsset horizon.Asset, quoteAsset horizon.Asset) (*model.Order, error) {
orderAction := model.OrderActionSell
price := model.NumberFromFloat(float64(mob.MO.Price.N)/float64(mob.MO.Price.D), utils.SdexPrecision)
volume := model.NumberFromFloat(float64(mob.MO.Amount)/math.Pow(10, 7), utils.SdexPrecision)
isBuy, e := assetsEqual(quoteAsset, mob.MO.Selling)
if e != nil {
return nil, fmt.Errorf("could not compare assets, error: %s", e)
}
if isBuy {
orderAction = model.OrderActionBuy
// TODO need to test price and volume conversions correctly
// volume calculation needs to happen first since it uses the non-inverted price when multiplying
volume = model.NumberFromFloat(volume.AsFloat()*price.AsFloat(), utils.SdexPrecision)
price = model.InvertNumber(price)
}
return &model.Order{
Pair: &model.TradingPair{
Base: model.FromHorizonAsset(baseAsset),
Quote: model.FromHorizonAsset(quoteAsset),
},
OrderAction: orderAction,
OrderType: model.OrderTypeLimit,
Price: price,
Volume: volume,
Timestamp: model.MakeTimestamp(time.Now().UnixNano() / int64(time.Millisecond)),
}, nil
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hah, I just committed my own version before I saw this, let me know if I've got it. |
||
//b, e := api.LoadOrderBook(*assetBase, *assetQuote) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can remove commented out code for now There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
baseAsset, quoteAsset, e := sdex.pair2Assets() | ||
if e != nil { | ||
log.Printf("%s", e) | ||
return | ||
} | ||
b, e := sdex.API.LoadOrderBook(baseAsset, quoteAsset) | ||
if e != nil { | ||
log.Printf("Can't get SDEX orderbook: %s\n", e) | ||
return | ||
} | ||
return b, e | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package plugins | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/interstellar/kelp/api" | ||
"github.com/interstellar/kelp/model" | ||
"github.com/interstellar/kelp/support/utils" | ||
"github.com/stellar/go/clients/horizon" | ||
) | ||
|
||
// sdexFeed represents a pricefeed from the SDEX | ||
type sdexFeed struct { | ||
sdex *SDEX | ||
assetBase *horizon.Asset | ||
assetQuote *horizon.Asset | ||
} | ||
|
||
// ensure that it implements PriceFeed | ||
var _ api.PriceFeed = &sdexFeed{} | ||
|
||
// makeSDEXFeed creates a price feed from buysell's url fields | ||
func makeSDEXFeed(url string) (*sdexFeed, error) { | ||
urlParts := strings.Split(url, "/") | ||
|
||
baseParts := strings.Split(urlParts[0], ":") | ||
baseCode := baseParts[0] | ||
baseIssuer := baseParts[1] | ||
baseConvert, e := utils.ParseAsset(baseCode, baseIssuer) | ||
if e != nil { | ||
return nil, fmt.Errorf("unable to convert base asset url to sdex asset: %s", e) | ||
} | ||
|
||
quoteParts := strings.Split(urlParts[1], ":") | ||
quoteCode := quoteParts[0] | ||
quoteIssuer := quoteParts[1] | ||
quoteConvert, e := utils.ParseAsset(quoteCode, quoteIssuer) | ||
if e != nil { | ||
return nil, fmt.Errorf("unable to convert quote asset url to sdex asset: %s", e) | ||
} | ||
|
||
tradingPair := &model.TradingPair{ | ||
Base: model.Asset(utils.Asset2CodeString(*baseConvert)), | ||
Quote: model.Asset(utils.Asset2CodeString(*quoteConvert)), | ||
} | ||
|
||
sdexAssetMap := map[model.Asset]horizon.Asset{ | ||
tradingPair.Base: *baseConvert, | ||
tradingPair.Quote: *quoteConvert, | ||
} | ||
|
||
feedSDEX := MakeSDEX( | ||
Reidmcc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
PrivateSdexHack.API, | ||
"", | ||
"", | ||
"", | ||
"", | ||
PrivateSdexHack.Network, | ||
Reidmcc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
nil, | ||
0, | ||
0, | ||
true, | ||
tradingPair, | ||
sdexAssetMap, | ||
) | ||
|
||
return &sdexFeed{ | ||
sdex: feedSDEX, | ||
assetBase: baseConvert, | ||
assetQuote: quoteConvert, | ||
}, nil | ||
} | ||
|
||
// GetPrice returns the SDEX mid price for the trading pair | ||
func (s *sdexFeed) GetPrice() (float64, error) { | ||
orderBook, e := s.sdex.GetOrderBook(s.sdex.pair) | ||
if e != nil { | ||
return 0, fmt.Errorf("unable to get sdex price: %s", e) | ||
} | ||
|
||
bids := orderBook.Bids | ||
topBidPrice := utils.PriceAsFloat(bids[0].Price) | ||
Reidmcc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
asks := orderBook.Asks | ||
lowAskPrice := utils.PriceAsFloat(asks[0].Price) | ||
|
||
centerPrice := (topBidPrice + lowAskPrice) / 2 | ||
return centerPrice, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be
client
(notsdex.API
) andutils.ParseNetwork(botConfig.HorizonURL)
instead ofsdex.Network
(can extract into anetwork
variable first.it's reasonable for MakeSDEX to do something like this if it needs to:
API = nil
since that's an abstraction we get with the make factory method. So when we reach into the sdex.API here we're breaking that abstraction and creating a dependency where there shouldn't be.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done