Skip to content
This repository has been archived by the owner on Apr 30, 2020. It is now read-only.

Commit

Permalink
simulate use market depth
Browse files Browse the repository at this point in the history
  • Loading branch information
miaolz123 committed Oct 7, 2016
1 parent b30dcb7 commit e185cd9
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 95 deletions.
3 changes: 1 addition & 2 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ type Exchange interface {
SetLimit(times interface{}) float64
AutoSleep()
GetMinAmount(stock string) float64
Simulate(balance, btc, ltc interface{}) bool
GetAccount() interface{}
Buy(stockType string, price, amount interface{}, msgs ...interface{}) interface{}
Sell(stockType string, price, amount interface{}, msgs ...interface{}) interface{}
Expand All @@ -32,5 +31,5 @@ type Exchange interface {
GetTrades(stockType string) interface{}
CancelOrder(order Order) bool
GetTicker(stockType string, sizes ...interface{}) interface{}
GetRecords(stockType, period string, sizes ...interface{}) []Record
GetRecords(stockType, period string, sizes ...interface{}) interface{}
}
30 changes: 14 additions & 16 deletions api/huobi.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,11 @@ func NewHuobi(opt Option) *Huobi {
constant.BTC: 0.001,
constant.LTC: 0.01,
},
records: make(map[string][]Record),
host: "https://api.huobi.com/apiv3",
logger: model.Logger{TraderID: opt.TraderID, ExchangeType: opt.Type},
option: opt,
records: make(map[string][]Record),
host: "https://api.huobi.com/apiv3",
logger: model.Logger{TraderID: opt.TraderID, ExchangeType: opt.Type},
option: opt,

limit: 10.0,
lastSleep: time.Now().UnixNano(),
}
Expand Down Expand Up @@ -223,15 +224,12 @@ func (e *Huobi) Buy(stockType string, _price, _amount interface{}, msgs ...inter
e.logger.Log(constant.ERROR, 0.0, 0.0, "Buy() error, ", err)
return false
}
if price < ticker.Sell {
e.logger.Log(constant.ERROR, 0.0, 0.0, "Buy() error, order price must be greater than market sell price")
return false
}
if price*amount > e.account.Balance {
total := simulateBuy(amount, ticker)
if total > e.account.Balance {
e.logger.Log(constant.ERROR, 0.0, 0.0, "Buy() error, balance is not enough")
return false
}
e.account.Balance -= ticker.Sell * amount
e.account.Balance -= total
if stockType == constant.LTC {
e.account.LTC += amount
} else {
Expand Down Expand Up @@ -294,7 +292,7 @@ func (e *Huobi) Sell(stockType string, _price, _amount interface{}, msgs ...inte
}
e.account.BTC -= amount
}
e.account.Balance += ticker.Buy * amount
e.account.Balance += simulateSell(amount, ticker)
e.logger.Log(constant.SELL, price, amount, msgs...)
return fmt.Sprint(time.Now().Unix())
}
Expand Down Expand Up @@ -511,14 +509,14 @@ func (e *Huobi) GetTicker(stockType string, sizes ...interface{}) interface{} {
}

// GetRecords : get candlestick data
func (e *Huobi) GetRecords(stockType, period string, sizes ...interface{}) (records []Record) {
func (e *Huobi) GetRecords(stockType, period string, sizes ...interface{}) interface{} {
if _, ok := e.stockMap[stockType]; !ok {
e.logger.Log(constant.ERROR, 0.0, 0.0, "GetRecords() error, unrecognized stockType: ", stockType)
return
return false
}
if _, ok := e.periodMap[period]; !ok {
e.logger.Log(constant.ERROR, 0.0, 0.0, "GetRecords() error, unrecognized period: ", period)
return
return false
}
size := 200
if len(sizes) > 0 && conver.IntMust(sizes[0]) > 0 {
Expand All @@ -527,12 +525,12 @@ func (e *Huobi) GetRecords(stockType, period string, sizes ...interface{}) (reco
resp, err := get(fmt.Sprint("http://api.huobi.com/staticmarket/", strings.ToLower(stockType), "_kline_", e.periodMap[period], "_json.js"))
if err != nil {
e.logger.Log(constant.ERROR, 0.0, 0.0, "GetRecords() error, ", err)
return
return false
}
json, err := simplejson.NewJson(resp)
if err != nil {
e.logger.Log(constant.ERROR, 0.0, 0.0, "GetRecords() error, ", err)
return
return false
}
timeLast := int64(0)
if len(e.records[period]) > 0 {
Expand Down
30 changes: 14 additions & 16 deletions api/okcoin.cn.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,11 @@ func NewOKCoinCn(opt Option) *OKCoinCn {
constant.BTC: 0.01,
constant.LTC: 0.1,
},
records: make(map[string][]Record),
host: "https://www.okcoin.cn/api/v1/",
logger: model.Logger{TraderID: opt.TraderID, ExchangeType: opt.Type},
option: opt,
records: make(map[string][]Record),
host: "https://www.okcoin.cn/api/v1/",
logger: model.Logger{TraderID: opt.TraderID, ExchangeType: opt.Type},
option: opt,

limit: 10.0,
lastSleep: time.Now().UnixNano(),
}
Expand Down Expand Up @@ -211,15 +212,12 @@ func (e *OKCoinCn) Buy(stockType string, _price, _amount interface{}, msgs ...in
e.logger.Log(constant.ERROR, 0.0, 0.0, "Buy() error, ", err)
return false
}
if price < ticker.Sell {
e.logger.Log(constant.ERROR, 0.0, 0.0, "Buy() error, order price must be greater than market sell price")
return false
}
if price*amount > e.account.Balance {
total := simulateBuy(amount, ticker)
if total > e.account.Balance {
e.logger.Log(constant.ERROR, 0.0, 0.0, "Buy() error, balance is not enough")
return false
}
e.account.Balance -= ticker.Sell * amount
e.account.Balance -= total
if stockType == constant.LTC {
e.account.LTC += amount
} else {
Expand Down Expand Up @@ -283,7 +281,7 @@ func (e *OKCoinCn) Sell(stockType string, _price, _amount interface{}, msgs ...i
}
e.account.BTC -= amount
}
e.account.Balance += ticker.Buy * amount
e.account.Balance += simulateSell(amount, ticker)
e.logger.Log(constant.SELL, price, amount, msgs...)
return fmt.Sprint(time.Now().Unix())
}
Expand Down Expand Up @@ -503,14 +501,14 @@ func (e *OKCoinCn) GetTicker(stockType string, sizes ...interface{}) interface{}
}

// GetRecords : get candlestick data
func (e *OKCoinCn) GetRecords(stockType, period string, sizes ...interface{}) (records []Record) {
func (e *OKCoinCn) GetRecords(stockType, period string, sizes ...interface{}) interface{} {
if _, ok := e.stockMap[stockType]; !ok {
e.logger.Log(constant.ERROR, 0.0, 0.0, "GetRecords() error, unrecognized stockType: ", stockType)
return
return false
}
if _, ok := e.periodMap[period]; !ok {
e.logger.Log(constant.ERROR, 0.0, 0.0, "GetRecords() error, unrecognized period: ", period)
return
return false
}
size := 200
if len(sizes) > 0 && conver.IntMust(sizes[0]) > 0 {
Expand All @@ -519,12 +517,12 @@ func (e *OKCoinCn) GetRecords(stockType, period string, sizes ...interface{}) (r
resp, err := get(fmt.Sprint(e.host, "kline.do?symbol=", e.stockMap[stockType], "_cny&type=", e.periodMap[period], "&size=", size))
if err != nil {
e.logger.Log(constant.ERROR, 0.0, 0.0, "GetRecords() error, ", err)
return
return false
}
json, err := simplejson.NewJson(resp)
if err != nil {
e.logger.Log(constant.ERROR, 0.0, 0.0, "GetRecords() error, ", err)
return
return false
}
timeLast := int64(0)
if len(e.records[period]) > 0 {
Expand Down
97 changes: 36 additions & 61 deletions api/poloniex.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type Poloniex struct {
option Option

simulate bool
account Account
account map[string]float64
orders map[string]Order

limit float64
Expand Down Expand Up @@ -169,10 +169,13 @@ func NewPoloniex(opt Option) *Poloniex {
constant.BTC: 0.01,
constant.LTC: 0.1,
},
records: make(map[string][]Record),
host: "https://poloniex.com/",
logger: model.Logger{TraderID: opt.TraderID, ExchangeType: opt.Type},
option: opt,
records: make(map[string][]Record),
host: "https://poloniex.com/",
logger: model.Logger{TraderID: opt.TraderID, ExchangeType: opt.Type},
option: opt,

account: make(map[string]float64),

limit: 10.0,
lastSleep: time.Now().UnixNano(),
}
Expand Down Expand Up @@ -263,41 +266,18 @@ func (e *Poloniex) getAuthJSON(url string, params []string) (data []byte, json *
}

// Simulate : set the account of simulation
func (e *Poloniex) Simulate(balance, btc, ltc interface{}) bool {
func (e *Poloniex) Simulate(acc map[string]interface{}) bool {
e.simulate = true
// e.orders = make(map[string]Order)
e.account = Account{
Balance: conver.Float64Must(balance),
BTC: conver.Float64Must(btc),
LTC: conver.Float64Must(ltc),
for k, v := range acc {
e.account[k] = conver.Float64Must(v)
}
return true
}

// GetAccount : get the account detail of this exchange
func (e *Poloniex) GetAccount() interface{} {
if e.simulate {
e.account.Total = e.account.Balance + e.account.FrozenBalance
ticker, err := e.getTicker(constant.BTC, 10)
if err != nil {
e.logger.Log(constant.ERROR, 0.0, 0.0, "GetAccount() error, ", err)
return false
}
e.account.Total += ticker.Mid * (e.account.BTC + e.account.FrozenBTC)
ticker, err = e.getTicker(constant.LTC, 10)
if err != nil {
e.logger.Log(constant.ERROR, 0.0, 0.0, "GetAccount() error, ", err)
return false
}
e.account.Total += ticker.Mid * (e.account.LTC + e.account.FrozenLTC)
e.account.Net = e.account.Total
if e.option.MainStock == constant.LTC {
e.account.Stock = e.account.LTC
e.account.FrozenStock = e.account.FrozenLTC
} else {
e.account.Stock = e.account.BTC
e.account.FrozenStock = e.account.FrozenBTC
}
return e.account
}
data, jsoner, err := e.getAuthJSON(e.host+"tradingApi", []string{
Expand Down Expand Up @@ -347,25 +327,22 @@ func (e *Poloniex) Buy(stockType string, _price, _amount interface{}, msgs ...in
return false
}
if e.simulate {
types := strings.Split(stockType, "_")
if len(types) < 2 {
e.logger.Log(constant.ERROR, 0.0, 0.0, "Buy() error, unrecognized stockType: ", stockType)
}
ticker, err := e.getTicker(stockType, 10)
if err != nil {
e.logger.Log(constant.ERROR, 0.0, 0.0, "Buy() error, ", err)
return false
}
if price < ticker.Sell {
e.logger.Log(constant.ERROR, 0.0, 0.0, "Buy() error, order price must be greater than market sell price")
total := simulateBuy(amount, ticker)
if total > e.account[types[0]] {
e.logger.Log(constant.ERROR, 0.0, 0.0, "Buy() error, ", types[0], " is not enough")
return false
}
if price*amount > e.account.Balance {
e.logger.Log(constant.ERROR, 0.0, 0.0, "Buy() error, balance is not enough")
return false
}
e.account.Balance -= ticker.Sell * amount
if stockType == constant.LTC {
e.account.LTC += amount
} else {
e.account.BTC += amount
}
e.account[types[0]] -= total
e.account[types[1]] += amount
e.logger.Log(constant.BUY, price, amount, msgs...)
return fmt.Sprint(time.Now().Unix())
}
Expand Down Expand Up @@ -396,6 +373,10 @@ func (e *Poloniex) Sell(stockType string, _price, _amount interface{}, msgs ...i
return false
}
if e.simulate {
types := strings.Split(stockType, "_")
if len(types) < 2 {
e.logger.Log(constant.ERROR, 0.0, 0.0, "Buy() error, unrecognized stockType: ", stockType)
}
ticker, err := e.getTicker(stockType, 10)
if err != nil {
e.logger.Log(constant.ERROR, 0.0, 0.0, "Sell() error, ", err)
Expand All @@ -405,20 +386,12 @@ func (e *Poloniex) Sell(stockType string, _price, _amount interface{}, msgs ...i
e.logger.Log(constant.ERROR, 0.0, 0.0, "Sell() error, order price must be lesser than market buy price")
return false
}
if stockType == constant.LTC {
if amount > e.account.LTC {
e.logger.Log(constant.ERROR, 0.0, 0.0, "Sell() error, stock is not enough")
return false
}
e.account.LTC -= amount
} else {
if amount > e.account.BTC {
e.logger.Log(constant.ERROR, 0.0, 0.0, "Sell() error, stock is not enough")
return false
}
e.account.BTC -= amount
if amount > e.account[types[1]] {
e.logger.Log(constant.ERROR, 0.0, 0.0, "Sell() error, ", e.account[types[1]], " is not enough")
return false
}
e.account.Balance += ticker.Buy * amount
e.account[types[1]] -= amount
e.account[types[0]] += simulateSell(amount, ticker)
e.logger.Log(constant.SELL, price, amount, msgs...)
return fmt.Sprint(time.Now().Unix())
}
Expand Down Expand Up @@ -543,6 +516,7 @@ func (e *Poloniex) CancelOrder(order Order) bool {

// getTicker : get market ticker & depth
func (e *Poloniex) getTicker(stockType string, sizes ...interface{}) (ticker Ticker, err error) {
e.lastTimes++
if _, ok := e.stockMap[stockType]; !ok {
err = fmt.Errorf("GetTicker() error, unrecognized stockType: %+v", stockType)
return
Expand Down Expand Up @@ -598,14 +572,15 @@ func (e *Poloniex) GetTicker(stockType string, sizes ...interface{}) interface{}
}

// GetRecords : get candlestick data
func (e *Poloniex) GetRecords(stockType, period string, sizes ...interface{}) (records []Record) {
func (e *Poloniex) GetRecords(stockType, period string, sizes ...interface{}) interface{} {
e.lastTimes++
if _, ok := e.stockMap[stockType]; !ok {
e.logger.Log(constant.ERROR, 0.0, 0.0, "GetRecords() error, unrecognized stockType: ", stockType)
return
return false
}
if _, ok := e.periodMap[period]; !ok {
e.logger.Log(constant.ERROR, 0.0, 0.0, "GetRecords() error, unrecognized period: ", period)
return
return false
}
size := 200
if len(sizes) > 0 && conver.IntMust(sizes[0]) > 0 {
Expand All @@ -619,12 +594,12 @@ func (e *Poloniex) GetRecords(stockType, period string, sizes ...interface{}) (r
resp, err := get(fmt.Sprint(e.host, "public?command=returnChartData&currencyPair=", e.stockMap[stockType], "&start=", start, "&end=9999999999&period=", e.periodMap[period]))
if err != nil {
e.logger.Log(constant.ERROR, 0.0, 0.0, "GetRecords() error, ", err)
return
return false
}
json, err := simplejson.NewJson(resp)
if err != nil {
e.logger.Log(constant.ERROR, 0.0, 0.0, "GetRecords() error, ", err)
return
return false
}
timeLast := int64(0)
if len(e.records[period]) > 0 {
Expand Down
41 changes: 41 additions & 0 deletions api/simulate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package api

func simulateBuy(amount float64, ticker Ticker) (total float64) {
if len(ticker.Asks) < 1 {
return ticker.Sell * amount
}
dealAmount := 0.0
for _, orderBook := range ticker.Asks {
if dealAmount+orderBook.Amount >= amount {
total += (amount - dealAmount) * orderBook.Price
dealAmount = amount
break
}
total += orderBook.Amount * orderBook.Price
dealAmount += orderBook.Amount
}
if dealAmount < amount {
total += (amount - dealAmount) * ticker.Asks[len(ticker.Asks)-1].Price
}
return
}

func simulateSell(amount float64, ticker Ticker) (total float64) {
if len(ticker.Bids) < 1 {
return ticker.Buy * amount
}
dealAmount := 0.0
for _, orderBook := range ticker.Bids {
if dealAmount+orderBook.Amount >= amount {
total += (amount - dealAmount) * orderBook.Price
dealAmount = amount
break
}
total += orderBook.Amount * orderBook.Price
dealAmount += orderBook.Amount
}
if dealAmount < amount {
total += (amount - dealAmount) * ticker.Bids[len(ticker.Bids)-1].Price
}
return
}

0 comments on commit e185cd9

Please sign in to comment.