mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 23:16:45 +00:00
Add basic support for COINUT exchange
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
|
||||
A cryptocurrency trading bot supporting multiple exchanges written in Golang.
|
||||
A cryptocurrency trading bot supporting multiple exchanges written in Golang.
|
||||
|
||||
**Please note that this bot is under development and is not ready for production!**
|
||||
|
||||
@@ -19,12 +19,13 @@ A cryptocurrency trading bot supporting multiple exchanges written in Golang.
|
||||
| BTCC | Yes | Yes | No |
|
||||
| BTCE | Yes | NA | NA |
|
||||
| BTCMarkets | Yes | NA | NA |
|
||||
| COINUT | Yes | No | NA |
|
||||
| GDAX(Coinbase) | Yes | Yes | No|
|
||||
| Gemini | Yes | NA | NA |
|
||||
| Huobi | Yes | Yes |No |
|
||||
| ItBit | Yes | NA | NA |
|
||||
| Kraken | Yes | NA | NA |
|
||||
| LakeBTC | Yes | No | NA |
|
||||
| LakeBTC | Yes | No | NA |
|
||||
| Liqui | Yes | No | NA |
|
||||
| LocalBitcoins | Yes | NA | NA |
|
||||
| OKCoin (both) | Yes | Yes | No |
|
||||
@@ -70,4 +71,3 @@ Run the application!
|
||||
|
||||
## Binaries
|
||||
Binaries will be published once the codebase reaches a stable condition.
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ func (c *Config) CheckExchangeConfigValues() error {
|
||||
c.Exchanges[i].AuthenticatedAPISupport = false
|
||||
log.Printf(WarningExchangeAuthAPIDefaultOrEmptyValues, exch.Name)
|
||||
continue
|
||||
} else if exch.Name == "ITBIT" || exch.Name == "Bitstamp" || exch.Name == "Coinbase" {
|
||||
} else if exch.Name == "ITBIT" || exch.Name == "Bitstamp" || exch.Name == "COINUT" || exch.Name == "GDAX" {
|
||||
if exch.ClientID == "" || exch.ClientID == "ClientID" {
|
||||
c.Exchanges[i].AuthenticatedAPISupport = false
|
||||
log.Printf(WarningExchangeAuthAPIDefaultOrEmptyValues, exch.Name)
|
||||
|
||||
@@ -129,6 +129,20 @@
|
||||
"EnabledPairs": "LTC,BTC",
|
||||
"BaseCurrencies": "AUD"
|
||||
},
|
||||
{
|
||||
"Name": "COINUT",
|
||||
"Enabled": true,
|
||||
"Verbose": false,
|
||||
"Websocket": false,
|
||||
"RESTPollingDelay": 10,
|
||||
"AuthenticatedAPISupport": false,
|
||||
"APIKey": "Key",
|
||||
"APISecret": "Secret",
|
||||
"ClientID": "ClientID",
|
||||
"AvailablePairs": "LTCBTC,ETCBTC,ETHBTC",
|
||||
"EnabledPairs": "LTCBTC,ETCBTC,ETHBTC",
|
||||
"BaseCurrencies": "USD"
|
||||
},
|
||||
{
|
||||
"Name": "GDAX",
|
||||
"Enabled": true,
|
||||
@@ -284,4 +298,4 @@
|
||||
"BaseCurrencies": "USD"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
324
exchanges/coinut/coinut.go
Normal file
324
exchanges/coinut/coinut.go
Normal file
@@ -0,0 +1,324 @@
|
||||
package coinut
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
)
|
||||
|
||||
const (
|
||||
COINUT_API_URL = "https://api.coinut.com"
|
||||
COINUT_API_VERISON = "1"
|
||||
COINUT_INSTRUMENTS = "inst_list"
|
||||
COINUT_TICKER = "inst_tick"
|
||||
COINUT_ORDERBOOK = "inst_order_book"
|
||||
COINUT_TRADES = "inst_trade"
|
||||
COINUT_BALANCE = "user_balance"
|
||||
COINUT_ORDER = "new_order"
|
||||
COINUT_ORDERS = "new_orders"
|
||||
COINUT_ORDERS_OPEN = "user_open_orders"
|
||||
COINUT_ORDER_CANCEL = "cancel_order"
|
||||
COINUT_ORDERS_CANCEL = "cancel_orders"
|
||||
COINUT_TRADE_HISTORY = "trade_history"
|
||||
COINUT_INDEX_TICKER = "index_tick"
|
||||
COINUT_OPTION_CHAIN = "option_chain"
|
||||
COINUT_POSITION_HISTORY = "position_history"
|
||||
COINUT_POSITION_OPEN = "user_open_positions"
|
||||
)
|
||||
|
||||
type COINUT struct {
|
||||
exchange.ExchangeBase
|
||||
WebsocketConn *websocket.Conn
|
||||
InstrumentMap map[string]int
|
||||
}
|
||||
|
||||
func (c *COINUT) SetDefaults() {
|
||||
c.Name = "COINUT"
|
||||
c.Enabled = false
|
||||
c.Verbose = false
|
||||
c.TakerFee = 0.1 //spot
|
||||
c.MakerFee = 0
|
||||
c.Verbose = false
|
||||
c.Websocket = false
|
||||
c.RESTPollingDelay = 10
|
||||
}
|
||||
|
||||
func (c *COINUT) Setup(exch config.ExchangeConfig) {
|
||||
if !exch.Enabled {
|
||||
c.SetEnabled(false)
|
||||
} else {
|
||||
c.Enabled = true
|
||||
c.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
c.SetAPIKeys(exch.APIKey, exch.APISecret, exch.ClientID, true)
|
||||
c.RESTPollingDelay = exch.RESTPollingDelay
|
||||
c.Verbose = exch.Verbose
|
||||
c.Websocket = exch.Websocket
|
||||
c.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",")
|
||||
c.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",")
|
||||
c.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",")
|
||||
}
|
||||
}
|
||||
|
||||
func (c *COINUT) GetInstruments() (CoinutInstruments, error) {
|
||||
var result CoinutInstruments
|
||||
params := make(map[string]interface{})
|
||||
params["sec_type"] = "SPOT"
|
||||
err := c.SendAuthenticatedHTTPRequest(COINUT_INSTRUMENTS, params, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *COINUT) GetInstrumentTicker(instrumentID int) (CoinutTicker, error) {
|
||||
var result CoinutTicker
|
||||
params := make(map[string]interface{})
|
||||
params["inst_id"] = instrumentID
|
||||
err := c.SendAuthenticatedHTTPRequest(COINUT_TICKER, params, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *COINUT) GetInstrumentOrderbook(instrumentID, limit int) (CoinutOrderbook, error) {
|
||||
var result CoinutOrderbook
|
||||
params := make(map[string]interface{})
|
||||
params["inst_id"] = instrumentID
|
||||
if limit > 0 {
|
||||
params["top_n"] = limit
|
||||
}
|
||||
err := c.SendAuthenticatedHTTPRequest(COINUT_ORDERBOOK, params, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *COINUT) GetTrades(instrumentID int) (CoinutTrades, error) {
|
||||
var result CoinutTrades
|
||||
params := make(map[string]interface{})
|
||||
params["inst_id"] = instrumentID
|
||||
err := c.SendAuthenticatedHTTPRequest(COINUT_TRADES, params, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *COINUT) GetUserBalance() (CoinutUserBalance, error) {
|
||||
result := CoinutUserBalance{}
|
||||
err := c.SendAuthenticatedHTTPRequest(COINUT_BALANCE, nil, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *COINUT) NewOrder(instrumentID int, quantity, price float64, buy bool, orderID uint32) (interface{}, error) {
|
||||
var result interface{}
|
||||
params := make(map[string]interface{})
|
||||
params["inst_id"] = instrumentID
|
||||
params["price"] = price
|
||||
params["qty"] = quantity
|
||||
params["side"] = "BUY"
|
||||
if !buy {
|
||||
params["side"] = "SELL"
|
||||
}
|
||||
params["client_ord_id"] = orderID
|
||||
|
||||
err := c.SendAuthenticatedHTTPRequest(COINUT_ORDER, params, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *COINUT) NewOrders(orders []CoinutOrder) ([]CoinutOrdersBase, error) {
|
||||
var result CoinutOrdersResponse
|
||||
params := make(map[string]interface{})
|
||||
params["orders"] = orders
|
||||
err := c.SendAuthenticatedHTTPRequest(COINUT_ORDERS, params, &result.Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.Data, nil
|
||||
}
|
||||
|
||||
func (c *COINUT) GetOpenOrders(instrumentID int) ([]CoinutOrdersResponse, error) {
|
||||
var result []CoinutOrdersResponse
|
||||
params := make(map[string]interface{})
|
||||
params["inst_id"] = instrumentID
|
||||
err := c.SendAuthenticatedHTTPRequest(COINUT_ORDERS_OPEN, params, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *COINUT) CancelOrder(instrumentID, orderID int) (bool, error) {
|
||||
var result CoinutGenericResponse
|
||||
params := make(map[string]interface{})
|
||||
params["inst_id"] = instrumentID
|
||||
params["order_id"] = orderID
|
||||
err := c.SendAuthenticatedHTTPRequest(COINUT_ORDERS_CANCEL, params, &result)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (c *COINUT) CancelOrders(orders []CoinutCancelOrders) (CoinutCancelOrdersResponse, error) {
|
||||
var result CoinutCancelOrdersResponse
|
||||
params := make(map[string]interface{})
|
||||
params["entries"] = orders
|
||||
err := c.SendAuthenticatedHTTPRequest(COINUT_ORDERS_CANCEL, params, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *COINUT) GetTradeHistory(instrumentID, start, limit int) (CoinutTradeHistory, error) {
|
||||
var result CoinutTradeHistory
|
||||
params := make(map[string]interface{})
|
||||
params["inst_id"] = instrumentID
|
||||
if start >= 0 && start <= 100 {
|
||||
params["start"] = start
|
||||
}
|
||||
if limit >= 0 && start <= 100 {
|
||||
params["limit"] = limit
|
||||
}
|
||||
err := c.SendAuthenticatedHTTPRequest(COINUT_TRADE_HISTORY, params, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *COINUT) GetIndexTicker(asset string) (CoinutIndexTicker, error) {
|
||||
var result CoinutIndexTicker
|
||||
params := make(map[string]interface{})
|
||||
params["asset"] = asset
|
||||
err := c.SendAuthenticatedHTTPRequest(COINUT_INDEX_TICKER, params, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *COINUT) GetDerivativeInstruments(secType string) (interface{}, error) {
|
||||
var result interface{} //to-do
|
||||
params := make(map[string]interface{})
|
||||
params["sec_type"] = secType
|
||||
err := c.SendAuthenticatedHTTPRequest(COINUT_INSTRUMENTS, params, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *COINUT) GetOptionChain(asset, secType string, expiry int64) (CoinutOptionChainResponse, error) {
|
||||
var result CoinutOptionChainResponse
|
||||
params := make(map[string]interface{})
|
||||
params["asset"] = asset
|
||||
params["sec_type"] = secType
|
||||
err := c.SendAuthenticatedHTTPRequest(COINUT_OPTION_CHAIN, params, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *COINUT) GetPositionHistory(secType string, start, limit int) (CoinutPositionHistory, error) {
|
||||
var result CoinutPositionHistory
|
||||
params := make(map[string]interface{})
|
||||
params["sec_type"] = secType
|
||||
if start >= 0 {
|
||||
params["start"] = start
|
||||
}
|
||||
if limit >= 0 {
|
||||
params["limit"] = limit
|
||||
}
|
||||
err := c.SendAuthenticatedHTTPRequest(COINUT_POSITION_HISTORY, params, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *COINUT) GetOpenPosition(instrumentID int) ([]CoinutOpenPosition, error) {
|
||||
type Response struct {
|
||||
Positions []CoinutOpenPosition `json:"positions"`
|
||||
}
|
||||
var result Response
|
||||
params := make(map[string]interface{})
|
||||
params["inst_id"] = instrumentID
|
||||
|
||||
err := c.SendAuthenticatedHTTPRequest(COINUT_POSITION_OPEN, params, &result)
|
||||
if err != nil {
|
||||
return result.Positions, err
|
||||
}
|
||||
return result.Positions, nil
|
||||
}
|
||||
|
||||
//to-do: user position update via websocket
|
||||
|
||||
func (c *COINUT) SendAuthenticatedHTTPRequest(apiRequest string, params map[string]interface{}, result interface{}) (err error) {
|
||||
timestamp := time.Now().Unix()
|
||||
payload := []byte("")
|
||||
|
||||
if params == nil {
|
||||
params = map[string]interface{}{}
|
||||
}
|
||||
params["nonce"] = timestamp
|
||||
params["request"] = apiRequest
|
||||
|
||||
payload, err = common.JSONEncode(params)
|
||||
|
||||
if err != nil {
|
||||
return errors.New("SendAuthenticatedHTTPRequest: Unable to JSON request")
|
||||
}
|
||||
|
||||
if c.Verbose {
|
||||
log.Printf("Request JSON: %s\n", payload)
|
||||
}
|
||||
|
||||
hmac := common.GetHMAC(common.HASH_SHA256, []byte(payload), []byte(c.APIKey))
|
||||
headers := make(map[string]string)
|
||||
headers["X-USER"] = c.ClientID
|
||||
headers["X-SIGNATURE"] = common.HexEncodeToString(hmac)
|
||||
headers["Content-Type"] = "application/json"
|
||||
|
||||
resp, err := common.SendHTTPRequest("POST", COINUT_API_URL, headers, bytes.NewBuffer(payload))
|
||||
|
||||
if c.Verbose {
|
||||
log.Printf("Recieved raw: \n%s", resp)
|
||||
}
|
||||
|
||||
genResp := CoinutGenericResponse{}
|
||||
|
||||
err = common.JSONDecode([]byte(resp), &genResp)
|
||||
|
||||
if err != nil {
|
||||
return errors.New("Unable to JSON Unmarshal generic response.")
|
||||
}
|
||||
|
||||
if genResp.Status[0] != "OK" {
|
||||
return errors.New("Status is not OK.")
|
||||
}
|
||||
|
||||
err = common.JSONDecode([]byte(resp), &result)
|
||||
|
||||
if err != nil {
|
||||
return errors.New("Unable to JSON Unmarshal response.")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
213
exchanges/coinut/coinut_types.go
Normal file
213
exchanges/coinut/coinut_types.go
Normal file
@@ -0,0 +1,213 @@
|
||||
package coinut
|
||||
|
||||
type CoinutGenericResponse struct {
|
||||
Nonce int64 `json:"nonce"`
|
||||
Reply string `json:"reply"`
|
||||
Status []string `json:"status"`
|
||||
TransID int64 `json:"trans_id"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
type CoinutInstrumentBase struct {
|
||||
Base string `json:"base"`
|
||||
DecimalPlaces int `json:"decimal_places"`
|
||||
InstID int `json:"inst_id"`
|
||||
Quote string `json:"quote"`
|
||||
}
|
||||
|
||||
type CoinutInstruments struct {
|
||||
Instruments map[string][]CoinutInstrumentBase `json:"SPOT"`
|
||||
}
|
||||
|
||||
type CoinutTicker struct {
|
||||
HighestBuy float64 `json:"highest_buy,string"`
|
||||
InstrumentID int `json:"inst_id"`
|
||||
Last float64 `json:"last,string"`
|
||||
LowestSell float64 `json:"lowest_sell,string"`
|
||||
OpenInterest float64 `json:"open_interest,string"`
|
||||
Timestamp float64 `json:"timestamp"`
|
||||
TransID int64 `json:"trans_id"`
|
||||
Volume float64 `json:"volume,string"`
|
||||
Volume24 float64 `json:"volume24,string"`
|
||||
}
|
||||
|
||||
type CoinutOrderbookBase struct {
|
||||
Count int `json:"count"`
|
||||
Price float64 `json:"price,string"`
|
||||
Quantity float64 `json:"quantity,string"`
|
||||
}
|
||||
|
||||
type CoinutOrderbook struct {
|
||||
Buy []CoinutOrderbookBase `json:"buy"`
|
||||
Sell []CoinutOrderbookBase `json:"sell"`
|
||||
InstrumentID int `json:"inst_id"`
|
||||
TotalBuy float64 `json:"total_buy,string"`
|
||||
TotalSell float64 `json:"total_sell,string"`
|
||||
TransID int64 `json:"trans_id"`
|
||||
}
|
||||
|
||||
type CoinutTradeBase struct {
|
||||
Price float64 `json:"price,string"`
|
||||
Quantity float64 `json:"quantity,string"`
|
||||
Side string `json:"side"`
|
||||
Timestamp float64 `json:"timestamp"`
|
||||
TransID int64 `json:"trans_id"`
|
||||
}
|
||||
|
||||
type CoinutTrades struct {
|
||||
Trades []CoinutTradeBase `json:"trades"`
|
||||
}
|
||||
|
||||
type CoinutUserBalance struct {
|
||||
BTC float64 `json:"btc,string"`
|
||||
ETC float64 `json:"etc,string"`
|
||||
ETH float64 `json:"eth,string"`
|
||||
LTC float64 `json:"ltc,string"`
|
||||
Equity float64 `json:"equity,string,string"`
|
||||
InitialMargin float64 `json:"initial_margin,string"`
|
||||
MaintenanceMargin float64 `json:"maintenance_margin,string"`
|
||||
RealizedPL float64 `json:"realized_pl,string"`
|
||||
TransID int64 `json:"trans_id"`
|
||||
UnrealizedPL float64 `json:"unrealized_pl,string"`
|
||||
}
|
||||
|
||||
type CoinutOrder struct {
|
||||
InstrumentID int64 `json:"inst_id"`
|
||||
Price float64 `json:"price,string"`
|
||||
Quantity float64 `json:"qty,string"`
|
||||
ClientOrderID int `json:"client_ord_id"`
|
||||
Side string `json:"side,string"`
|
||||
}
|
||||
|
||||
type CoinutOrderResponse struct {
|
||||
OrderID int64 `json:"order_id"`
|
||||
OpenQuantity float64 `json:"open_qty,string"`
|
||||
Price float64 `json:"price,string"`
|
||||
Quantity float64 `json:"qty,string"`
|
||||
InstrumentID int64 `json:"inst_id"`
|
||||
ClientOrderID int64 `json:"client_ord_id"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
OrderPrice float64 `json:"order_price,string"`
|
||||
Side string `json:"side"`
|
||||
}
|
||||
|
||||
type CoinutCommission struct {
|
||||
Currency string `json:"currency"`
|
||||
Amount float64 `json:"amount,string"`
|
||||
}
|
||||
|
||||
type CoinutOrderFilledResponse struct {
|
||||
CoinutGenericResponse
|
||||
Commission CoinutCommission `json:"commission"`
|
||||
FillPrice float64 `json:"fill_price,string"`
|
||||
FillQuantity float64 `json:"fill_qty,string"`
|
||||
Order CoinutOrderResponse `json:"order"`
|
||||
}
|
||||
|
||||
type CoinutOrderRejectResponse struct {
|
||||
CoinutOrderResponse
|
||||
Reasons []string `json:"reasons"`
|
||||
}
|
||||
|
||||
type CoinutOrdersBase struct {
|
||||
CoinutGenericResponse
|
||||
CoinutOrderResponse
|
||||
}
|
||||
|
||||
type CoinutOrdersResponse struct {
|
||||
Data []CoinutOrdersBase
|
||||
}
|
||||
|
||||
type CoinutCancelOrders struct {
|
||||
InstrumentID int `json:"int"`
|
||||
OrderID int64 `json:"order_id"`
|
||||
}
|
||||
|
||||
type CoinutCancelOrdersResponse struct {
|
||||
CoinutGenericResponse
|
||||
Results []struct {
|
||||
OrderID int64 `json:"order_id"`
|
||||
Status string `json:"status"`
|
||||
InstrumentID int `json:"inst_id"`
|
||||
} `json:"results"`
|
||||
}
|
||||
|
||||
type CoinutTradeHistory struct {
|
||||
TotalNumber int64 `json:"total_number"`
|
||||
Trades []CoinutOrderFilledResponse `json:"trades"`
|
||||
}
|
||||
|
||||
type CoinutIndexTicker struct {
|
||||
Asset string `json:"asset"`
|
||||
Price float64 `json:"price,string"`
|
||||
}
|
||||
|
||||
type CoinutOption struct {
|
||||
HighestBuy float64 `json:"highest_buy,string"`
|
||||
InstrumentID int `json:"inst_id"`
|
||||
Last float64 `json:"last,string"`
|
||||
LowestSell float64 `json:"lowest_sell,string"`
|
||||
OpenInterest float64 `json:"open_interest,string"`
|
||||
}
|
||||
|
||||
type CoinutOptionChainResponse struct {
|
||||
ExpiryTime int64 `json:"expiry_time"`
|
||||
SecurityType string `json:"sec_type"`
|
||||
Asset string `json:"asset"`
|
||||
Entries []struct {
|
||||
Call CoinutOption `json:"call"`
|
||||
Put CoinutOption `json:"put"`
|
||||
Strike float64 `json:"strike,string"`
|
||||
}
|
||||
}
|
||||
|
||||
type CoinutOptionChainUpdate struct {
|
||||
CoinutOption
|
||||
CoinutGenericResponse
|
||||
Asset string `json:"asset"`
|
||||
ExpiryTime int64 `json:"expiry_time"`
|
||||
SecurityType string `json:"sec_type"`
|
||||
Volume float64 `json:"volume,string"`
|
||||
}
|
||||
|
||||
type CoinutPositionHistory struct {
|
||||
Positions []struct {
|
||||
PositionID int `json:"position_id"`
|
||||
Records []struct {
|
||||
Commission CoinutCommission `json:"commission"`
|
||||
FillPrice float64 `json:"fill_price,string,omitempty"`
|
||||
TransactionID int `json:"trans_id"`
|
||||
FillQuantity float64 `json:"fill_qty,omitempty"`
|
||||
Position struct {
|
||||
Commission CoinutCommission `json:"commission"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
OpenPrice float64 `json:"open_price,string"`
|
||||
RealizedPL float64 `json:"realized_pl,string"`
|
||||
Quantity float64 `json:"qty,string"`
|
||||
} `json:"position"`
|
||||
AssetAtExpiry float64 `json:"asset_at_expiry,string,omitempty"`
|
||||
} `json:"records"`
|
||||
Instrument struct {
|
||||
ExpiryTime int64 `json:"expiry_time"`
|
||||
ContractSize float64 `json:"contract_size,string"`
|
||||
ConversionRate float64 `json:"conversion_rate,string"`
|
||||
OptionType string `json:"option_type"`
|
||||
InstrumentID int `json:"inst_id"`
|
||||
SecType string `json:"sec_type"`
|
||||
Asset string `json:"asset"`
|
||||
Strike float64 `json:"strike,string"`
|
||||
} `json:"inst"`
|
||||
OpenTimestamp int64 `json:"open_timestamp"`
|
||||
} `json:"positions"`
|
||||
TotalNumber int `json:"total_number"`
|
||||
}
|
||||
|
||||
type CoinutOpenPosition struct {
|
||||
PositionID int `json:"position_id"`
|
||||
Commission CoinutCommission `json:"commission"`
|
||||
OpenPrice float64 `json:"open_price,string"`
|
||||
RealizedPL float64 `json:"realized_pl,string"`
|
||||
Quantity float64 `json:"qty,string"`
|
||||
OpenTimestamp int64 `json:"open_timestamp"`
|
||||
InstrumentID int `json:"inst_id"`
|
||||
}
|
||||
60
exchanges/coinut/coinut_websocket.go
Normal file
60
exchanges/coinut/coinut_websocket.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package coinut
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
)
|
||||
|
||||
const COINUT_WEBSOCKET_URL = "wss://wsapi.coinut.com"
|
||||
|
||||
func (c *COINUT) WebsocketClient() {
|
||||
for c.Enabled && c.Websocket {
|
||||
var Dialer websocket.Dialer
|
||||
var err error
|
||||
c.WebsocketConn, _, err = Dialer.Dial(c.WebsocketURL, http.Header{})
|
||||
|
||||
if err != nil {
|
||||
log.Printf("%s Unable to connect to Websocket. Error: %s\n", c.Name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if c.Verbose {
|
||||
log.Printf("%s Connected to Websocket.\n", c.Name)
|
||||
}
|
||||
|
||||
err = c.WebsocketConn.WriteMessage(websocket.TextMessage, []byte(`{"messageType": "hello_world"}`))
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
for c.Enabled && c.Websocket {
|
||||
msgType, resp, err := c.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
break
|
||||
}
|
||||
|
||||
switch msgType {
|
||||
case websocket.TextMessage:
|
||||
type MsgType struct {
|
||||
MessageType string `json:"messageType"`
|
||||
}
|
||||
|
||||
msgType := MsgType{}
|
||||
err := common.JSONDecode(resp, &msgType)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
log.Println(string(resp))
|
||||
}
|
||||
}
|
||||
c.WebsocketConn.Close()
|
||||
log.Printf("%s Websocket client disconnected.", c.Name)
|
||||
}
|
||||
}
|
||||
129
exchanges/coinut/coinut_wrapper.go
Normal file
129
exchanges/coinut/coinut_wrapper.go
Normal file
@@ -0,0 +1,129 @@
|
||||
package coinut
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/currency/pair"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/stats"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
func (c *COINUT) Start() {
|
||||
go c.Run()
|
||||
}
|
||||
|
||||
func (c *COINUT) Run() {
|
||||
if c.Verbose {
|
||||
log.Printf("%s Websocket: %s. (url: %s).\n", c.GetName(), common.IsEnabled(c.Websocket), COINUT_WEBSOCKET_URL)
|
||||
log.Printf("%s polling delay: %ds.\n", c.GetName(), c.RESTPollingDelay)
|
||||
log.Printf("%s %d currencies enabled: %s.\n", c.GetName(), len(c.EnabledPairs), c.EnabledPairs)
|
||||
}
|
||||
|
||||
if c.Websocket {
|
||||
go c.WebsocketClient()
|
||||
}
|
||||
|
||||
exchangeProducts, err := c.GetInstruments()
|
||||
if err != nil {
|
||||
log.Printf("%s Failed to get available products.\n", c.GetName())
|
||||
return
|
||||
}
|
||||
|
||||
currencies := []string{}
|
||||
c.InstrumentMap = make(map[string]int)
|
||||
for x, y := range exchangeProducts.Instruments {
|
||||
c.InstrumentMap[x] = y[0].InstID
|
||||
currencies = append(currencies, x)
|
||||
}
|
||||
|
||||
err = c.UpdateAvailableCurrencies(currencies)
|
||||
if err != nil {
|
||||
log.Printf("%s Failed to get config.\n", c.GetName())
|
||||
}
|
||||
|
||||
for c.Enabled {
|
||||
for _, x := range c.EnabledPairs {
|
||||
currency := pair.NewCurrencyPair(x[0:3], x[3:])
|
||||
go func() {
|
||||
ticker, err := c.GetTickerPrice(currency)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
log.Printf("COINUT %s: Last %f High %f Low %f Volume %f\n", currency.Pair().String(), ticker.Last, ticker.High, ticker.Low, ticker.Volume)
|
||||
stats.AddExchangeInfo(c.GetName(), currency.GetFirstCurrency().String(), currency.GetSecondCurrency().String(), ticker.Last, ticker.Volume)
|
||||
}()
|
||||
}
|
||||
time.Sleep(time.Second * c.RESTPollingDelay)
|
||||
}
|
||||
}
|
||||
|
||||
//GetExchangeAccountInfo : Retrieves balances for all enabled currencies for the COINUT exchange
|
||||
func (e *COINUT) GetExchangeAccountInfo() (exchange.ExchangeAccountInfo, error) {
|
||||
var response exchange.ExchangeAccountInfo
|
||||
/*
|
||||
response.ExchangeName = e.GetName()
|
||||
accountBalance, err := e.GetAccounts()
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
for i := 0; i < len(accountBalance); i++ {
|
||||
var exchangeCurrency exchange.ExchangeAccountCurrencyInfo
|
||||
exchangeCurrency.CurrencyName = accountBalance[i].Currency
|
||||
exchangeCurrency.TotalValue = accountBalance[i].Available
|
||||
exchangeCurrency.Hold = accountBalance[i].Hold
|
||||
|
||||
response.Currencies = append(response.Currencies, exchangeCurrency)
|
||||
}
|
||||
*/
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (c *COINUT) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) {
|
||||
tickerNew, err := ticker.GetTicker(c.GetName(), p)
|
||||
if err == nil {
|
||||
return tickerNew, nil
|
||||
}
|
||||
|
||||
var tickerPrice ticker.TickerPrice
|
||||
tick, err := c.GetInstrumentTicker(c.InstrumentMap[p.Pair().String()])
|
||||
if err != nil {
|
||||
return ticker.TickerPrice{}, err
|
||||
}
|
||||
|
||||
tickerPrice.Pair = p
|
||||
tickerPrice.Volume = tick.Volume
|
||||
tickerPrice.Last = tick.Last
|
||||
tickerPrice.High = tick.HighestBuy
|
||||
tickerPrice.Low = tick.LowestSell
|
||||
ticker.ProcessTicker(c.GetName(), p, tickerPrice)
|
||||
return tickerPrice, nil
|
||||
}
|
||||
|
||||
func (c *COINUT) GetOrderbookEx(p pair.CurrencyPair) (orderbook.OrderbookBase, error) {
|
||||
ob, err := orderbook.GetOrderbook(c.GetName(), p)
|
||||
if err == nil {
|
||||
return ob, nil
|
||||
}
|
||||
|
||||
var orderBook orderbook.OrderbookBase
|
||||
orderbookNew, err := c.GetInstrumentOrderbook(c.InstrumentMap[p.Pair().String()], 200)
|
||||
if err != nil {
|
||||
return orderBook, err
|
||||
}
|
||||
|
||||
for x := range orderbookNew.Buy {
|
||||
orderBook.Bids = append(orderBook.Bids, orderbook.OrderbookItem{Amount: orderbookNew.Buy[x].Quantity, Price: orderbookNew.Buy[x].Price})
|
||||
}
|
||||
|
||||
for x := range orderbookNew.Sell {
|
||||
orderBook.Asks = append(orderBook.Asks, orderbook.OrderbookItem{Amount: orderbookNew.Sell[x].Quantity, Price: orderbookNew.Sell[x].Price})
|
||||
}
|
||||
orderBook.Pair = p
|
||||
orderbook.ProcessOrderbook(c.GetName(), p, orderBook)
|
||||
return orderBook, nil
|
||||
}
|
||||
3
main.go
3
main.go
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/btcc"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/btce"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/btcmarkets"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/coinut"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/gdax"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/gemini"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/huobi"
|
||||
@@ -41,6 +42,7 @@ type ExchangeMain struct {
|
||||
bitfinex bitfinex.Bitfinex
|
||||
btce btce.BTCE
|
||||
btcmarkets btcmarkets.BTCMarkets
|
||||
coinut coinut.COINUT
|
||||
gdax gdax.GDAX
|
||||
gemini gemini.Gemini
|
||||
okcoinChina okcoin.OKCoin
|
||||
@@ -119,6 +121,7 @@ func main() {
|
||||
new(bitfinex.Bitfinex),
|
||||
new(btce.BTCE),
|
||||
new(btcmarkets.BTCMarkets),
|
||||
new(coinut.COINUT),
|
||||
new(gdax.GDAX),
|
||||
new(gemini.Gemini),
|
||||
new(okcoin.OKCoin),
|
||||
|
||||
Reference in New Issue
Block a user