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

Commit

Permalink
closes #74: exchanges should have a price and volume precision compon…
Browse files Browse the repository at this point in the history
…ent for each trading pair (#76)
  • Loading branch information
nikhilsaraf committed Dec 4, 2018
1 parent 842e40e commit e38542c
Show file tree
Hide file tree
Showing 17 changed files with 225 additions and 105 deletions.
8 changes: 8 additions & 0 deletions api/exchange.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,18 @@ type FillTrackable interface {
GetLatestTradeCursor() (interface{}, error)
}

// Constrainable extracts out the method that SDEX can implement for now
type Constrainable interface {
// return nil if the constraint does not exist for the exchange
GetOrderConstraints(pair *model.TradingPair) *model.OrderConstraints
}

// TradeAPI is the interface we use as a generic API for trading on any crypto exchange
type TradeAPI interface {
GetAssetConverter() *model.AssetConverter

Constrainable

GetOrderBook(pair *model.TradingPair, maxCount int32) (*model.OrderBook, error)

GetTrades(pair *model.TradingPair, maybeCursor interface{}) (*TradesResult, error)
Expand Down
2 changes: 1 addition & 1 deletion cmd/trade.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ func init() {
)

dataKey := model.MakeSortedBotKey(assetBase, assetQuote)
strat, e := plugins.MakeStrategy(sdex, &assetBase, &assetQuote, *strategy, *stratConfigPath, *simMode)
strat, e := plugins.MakeStrategy(sdex, tradingPair, &assetBase, &assetQuote, *strategy, *stratConfigPath, *simMode)
if e != nil {
log.Println()
log.Println(e)
Expand Down
16 changes: 16 additions & 0 deletions model/orderbook.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,3 +227,19 @@ func (t Trade) String() string {
utils.CheckedString(t.Fee),
)
}

// OrderConstraints describes constraints when placing orders on an excahnge
type OrderConstraints struct {
PricePrecision int8
VolumePrecision int8
MinBaseVolume Number
}

// MakeOrderConstraints is a factory method for OrderConstraints
func MakeOrderConstraints(pricePrecision int8, volumePrecision int8, minBaseVolume float64) *OrderConstraints {
return &OrderConstraints{
PricePrecision: pricePrecision,
VolumePrecision: volumePrecision,
MinBaseVolume: *NumberFromFloat(minBaseVolume, volumePrecision),
}
}
8 changes: 8 additions & 0 deletions model/tradingPair.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ type TradingPair struct {
Quote Asset
}

// MakeTradingPair is a factory method
func MakeTradingPair(base Asset, quote Asset) *TradingPair {
return &TradingPair{
Base: base,
Quote: quote,
}
}

// String is the stringer function
func (p TradingPair) String() string {
s, e := p.ToString(Display, "/")
Expand Down
10 changes: 6 additions & 4 deletions plugins/balancedLevelProvider.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (

"github.com/interstellar/kelp/api"
"github.com/interstellar/kelp/model"
"github.com/interstellar/kelp/support/utils"
)

// balancedLevelProvider provides levels based on an exponential curve wrt. the number of assets held in the account.
Expand All @@ -27,6 +26,7 @@ type balancedLevelProvider struct {
carryoverInclusionProbability float64 // probability of including the carryover at a level that will be added
virtualBalanceBase float64 // virtual balance to use so we can smoothen out the curve
virtualBalanceQuote float64 // virtual balance to use so we can smoothen out the curve
orderConstraints *model.OrderConstraints

// precomputed before construction
randGen *rand.Rand
Expand All @@ -49,6 +49,7 @@ func makeBalancedLevelProvider(
carryoverInclusionProbability float64,
virtualBalanceBase float64,
virtualBalanceQuote float64,
orderConstraints *model.OrderConstraints,
) api.LevelProvider {
if minAmountSpread <= 0 {
log.Fatalf("minAmountSpread (%.7f) needs to be > 0 for the algorithm to work sustainably\n", minAmountSpread)
Expand Down Expand Up @@ -81,6 +82,7 @@ func makeBalancedLevelProvider(
carryoverInclusionProbability: carryoverInclusionProbability,
virtualBalanceBase: virtualBalanceBase,
virtualBalanceQuote: virtualBalanceQuote,
orderConstraints: orderConstraints,
randGen: randGen,
}
}
Expand Down Expand Up @@ -133,7 +135,7 @@ func (p *balancedLevelProvider) computeNewLevelWithCarryover(level api.Level, am
// include the amountCarryover we computed, price of the level remains unchanged
level = api.Level{
Price: level.Price,
Amount: *model.NumberFromFloat(level.Amount.AsFloat()+amountCarryoverToInclude, level.Amount.Precision()),
Amount: *level.Amount.Add(*model.NumberFromFloat(amountCarryoverToInclude, level.Amount.Precision())),
}

return level, amountCarryover
Expand Down Expand Up @@ -197,8 +199,8 @@ func (p *balancedLevelProvider) getLevel(maxAssetBase float64, maxAssetQuote flo
// since targetAmount needs to be less then what we've set above based on the inequality formula, let's reduce it by 5%
targetAmount *= (1 - p.getRandomSpread(p.minAmountSpread, p.maxAmountSpread))
level := api.Level{
Price: *model.NumberFromFloat(targetPrice, utils.SdexPrecision),
Amount: *model.NumberFromFloat(targetAmount, utils.SdexPrecision),
Price: *model.NumberFromFloat(targetPrice, p.orderConstraints.PricePrecision),
Amount: *model.NumberFromFloat(targetAmount, p.orderConstraints.VolumePrecision),
}
return level, nil
}
Expand Down
11 changes: 9 additions & 2 deletions plugins/balancedStrategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package plugins

import (
"github.com/interstellar/kelp/api"
"github.com/interstellar/kelp/model"
"github.com/interstellar/kelp/support/utils"
"github.com/stellar/go/clients/horizon"
)
Expand Down Expand Up @@ -31,12 +32,15 @@ func (c balancedConfig) String() string {
// makeBalancedStrategy is a factory method for balancedStrategy
func makeBalancedStrategy(
sdex *SDEX,
pair *model.TradingPair,
assetBase *horizon.Asset,
assetQuote *horizon.Asset,
config *balancedConfig,
) api.Strategy {
orderConstraints := sdex.GetOrderConstraints(pair)
sellSideStrategy := makeSellSideStrategy(
sdex,
orderConstraints,
assetBase,
assetQuote,
makeBalancedLevelProvider(
Expand All @@ -51,14 +55,16 @@ func makeBalancedStrategy(
config.MaxAmountCarryoverSpread,
config.CarryoverInclusionProbability,
config.VirtualBalanceBase,
config.VirtualBalanceQuote),
config.VirtualBalanceQuote,
orderConstraints),
config.PriceTolerance,
config.AmountTolerance,
false,
)
// switch sides of base/quote here for buy side
buySideStrategy := makeSellSideStrategy(
sdex,
orderConstraints,
assetQuote,
assetBase,
makeBalancedLevelProvider(
Expand All @@ -73,7 +79,8 @@ func makeBalancedStrategy(
config.MaxAmountCarryoverSpread,
config.CarryoverInclusionProbability,
config.VirtualBalanceQuote,
config.VirtualBalanceBase),
config.VirtualBalanceBase,
orderConstraints),
config.PriceTolerance,
config.AmountTolerance,
true,
Expand Down
7 changes: 7 additions & 0 deletions plugins/buysellStrategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"

"github.com/interstellar/kelp/api"
"github.com/interstellar/kelp/model"
"github.com/interstellar/kelp/support/utils"
"github.com/stellar/go/clients/horizon"
)
Expand Down Expand Up @@ -31,6 +32,7 @@ func (c buySellConfig) String() string {
// makeBuySellStrategy is a factory method
func makeBuySellStrategy(
sdex *SDEX,
pair *model.TradingPair,
assetBase *horizon.Asset,
assetQuote *horizon.Asset,
config *buySellConfig,
Expand All @@ -49,15 +51,18 @@ func makeBuySellStrategy(
if e != nil {
return nil, fmt.Errorf("cannot make the buysell strategy because we could not make the sell side feed pair: %s", e)
}
orderConstraints := sdex.GetOrderConstraints(pair)
sellSideStrategy := makeSellSideStrategy(
sdex,
orderConstraints,
assetBase,
assetQuote,
makeStaticSpreadLevelProvider(
config.Levels,
config.AmountOfABase,
offsetSell,
sellSideFeedPair,
orderConstraints,
),
config.PriceTolerance,
config.AmountTolerance,
Expand All @@ -82,13 +87,15 @@ func makeBuySellStrategy(
// switch sides of base/quote here for buy side
buySideStrategy := makeSellSideStrategy(
sdex,
orderConstraints,
assetQuote,
assetBase,
makeStaticSpreadLevelProvider(
config.Levels,
config.AmountOfABase,
offsetBuy,
buySideFeedPair,
orderConstraints,
),
config.PriceTolerance,
config.AmountTolerance,
Expand Down
6 changes: 6 additions & 0 deletions plugins/ccxtExchange.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ func (c ccxtExchange) GetAssetConverter() *model.AssetConverter {
return c.assetConverter
}

// GetOrderConstraints impl
func (c ccxtExchange) GetOrderConstraints(pair *model.TradingPair) *model.OrderConstraints {
// TODO implement
return nil
}

// GetAccountBalances impl
func (c ccxtExchange) GetAccountBalances(assetList []model.Asset) (map[model.Asset]model.Number, error) {
// TODO implement
Expand Down
12 changes: 8 additions & 4 deletions plugins/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"log"

"github.com/interstellar/kelp/api"
"github.com/interstellar/kelp/model"
"github.com/interstellar/kelp/support/utils"
"github.com/stellar/go/clients/horizon"
"github.com/stellar/go/support/config"
Expand All @@ -13,6 +14,7 @@ import (
// strategyFactoryData is a data container that has all the information needed to make a strategy
type strategyFactoryData struct {
sdex *SDEX
tradingPair *model.TradingPair
assetBase *horizon.Asset
assetQuote *horizon.Asset
stratConfigPath string
Expand Down Expand Up @@ -40,7 +42,7 @@ var strategies = map[string]StrategyContainer{
err := config.Read(strategyFactoryData.stratConfigPath, &cfg)
utils.CheckConfigError(cfg, err, strategyFactoryData.stratConfigPath)
utils.LogConfig(cfg)
s, e := makeBuySellStrategy(strategyFactoryData.sdex, strategyFactoryData.assetBase, strategyFactoryData.assetQuote, &cfg)
s, e := makeBuySellStrategy(strategyFactoryData.sdex, strategyFactoryData.tradingPair, strategyFactoryData.assetBase, strategyFactoryData.assetQuote, &cfg)
if e != nil {
return nil, fmt.Errorf("makeFn failed: %s", e)
}
Expand All @@ -57,7 +59,7 @@ var strategies = map[string]StrategyContainer{
err := config.Read(strategyFactoryData.stratConfigPath, &cfg)
utils.CheckConfigError(cfg, err, strategyFactoryData.stratConfigPath)
utils.LogConfig(cfg)
s, e := makeMirrorStrategy(strategyFactoryData.sdex, strategyFactoryData.assetBase, strategyFactoryData.assetQuote, &cfg, strategyFactoryData.simMode)
s, e := makeMirrorStrategy(strategyFactoryData.sdex, strategyFactoryData.tradingPair, strategyFactoryData.assetBase, strategyFactoryData.assetQuote, &cfg, strategyFactoryData.simMode)
if e != nil {
return nil, fmt.Errorf("makeFn failed: %s", e)
}
Expand All @@ -74,7 +76,7 @@ var strategies = map[string]StrategyContainer{
err := config.Read(strategyFactoryData.stratConfigPath, &cfg)
utils.CheckConfigError(cfg, err, strategyFactoryData.stratConfigPath)
utils.LogConfig(cfg)
s, e := makeSellStrategy(strategyFactoryData.sdex, strategyFactoryData.assetBase, strategyFactoryData.assetQuote, &cfg)
s, e := makeSellStrategy(strategyFactoryData.sdex, strategyFactoryData.tradingPair, strategyFactoryData.assetBase, strategyFactoryData.assetQuote, &cfg)
if e != nil {
return nil, fmt.Errorf("makeFn failed: %s", e)
}
Expand All @@ -91,7 +93,7 @@ var strategies = map[string]StrategyContainer{
err := config.Read(strategyFactoryData.stratConfigPath, &cfg)
utils.CheckConfigError(cfg, err, strategyFactoryData.stratConfigPath)
utils.LogConfig(cfg)
return makeBalancedStrategy(strategyFactoryData.sdex, strategyFactoryData.assetBase, strategyFactoryData.assetQuote, &cfg), nil
return makeBalancedStrategy(strategyFactoryData.sdex, strategyFactoryData.tradingPair, strategyFactoryData.assetBase, strategyFactoryData.assetQuote, &cfg), nil
},
},
"delete": StrategyContainer{
Expand All @@ -108,6 +110,7 @@ var strategies = map[string]StrategyContainer{
// MakeStrategy makes a strategy
func MakeStrategy(
sdex *SDEX,
tradingPair *model.TradingPair,
assetBase *horizon.Asset,
assetQuote *horizon.Asset,
strategy string,
Expand All @@ -121,6 +124,7 @@ func MakeStrategy(
}
s, e := strat.makeFn(strategyFactoryData{
sdex: sdex,
tradingPair: tradingPair,
assetBase: assetBase,
assetQuote: assetQuote,
stratConfigPath: stratConfigPath,
Expand Down

0 comments on commit e38542c

Please sign in to comment.