mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-21 07:26:48 +00:00
Engine improvements
This commit is contained in:
@@ -536,12 +536,21 @@ func TestSubmitOrder(t *testing.T) {
|
||||
if areTestAPIKeysSet(a) && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
var p = currency.Pair{
|
||||
Delimiter: "_",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USD,
|
||||
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Delimiter: "_",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USD,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := a.SubmitOrder(p, exchange.BuyOrderSide, exchange.LimitOrderType, 1, 1, "clientId")
|
||||
|
||||
response, err := a.SubmitOrder(orderSubmission)
|
||||
if !areTestAPIKeysSet(a) && err == nil {
|
||||
t.Error("Expecting an error when no keys are set")
|
||||
}
|
||||
|
||||
@@ -183,20 +183,25 @@ func (a *Alphapoint) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
|
||||
// GetExchangeHistory returns historic trade data since exchange opening.
|
||||
func (a *Alphapoint) GetExchangeHistory(p currency.Pair, assetType assets.AssetType) ([]exchange.TradeHistory, error) {
|
||||
var resp []exchange.TradeHistory
|
||||
|
||||
return resp, common.ErrNotYetImplemented
|
||||
return nil, common.ErrNotYetImplemented
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order and returns a true value when
|
||||
// successfully submitted
|
||||
func (a *Alphapoint) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, _ string) (exchange.SubmitOrderResponse, error) {
|
||||
func (a *Alphapoint) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
response, err := a.CreateOrder(p.String(),
|
||||
side.ToString(),
|
||||
orderType.ToString(),
|
||||
amount, price)
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
response, err := a.CreateOrder(order.Pair.String(),
|
||||
order.OrderSide.ToString(),
|
||||
order.OrderSide.ToString(),
|
||||
order.Amount, order.Price)
|
||||
|
||||
if response > 0 {
|
||||
submitOrderResponse.OrderID = fmt.Sprintf("%v", response)
|
||||
|
||||
@@ -259,13 +259,20 @@ func TestSubmitOrder(t *testing.T) {
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
var p = currency.Pair{
|
||||
Delimiter: "_",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USD,
|
||||
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Delimiter: "_",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USD,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := a.SubmitOrder(p,
|
||||
exchange.BuyOrderSide, exchange.LimitOrderType, 1, 1, "clientId")
|
||||
response, err := a.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -339,26 +339,33 @@ func (a *ANX) GetExchangeHistory(p currency.Pair, assetType assets.AssetType) ([
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (a *ANX) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, _ string) (exchange.SubmitOrderResponse, error) {
|
||||
func (a *ANX) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
var isBuying bool
|
||||
var limitPriceInSettlementCurrency float64
|
||||
|
||||
if side == exchange.BuyOrderSide {
|
||||
if order.OrderSide == exchange.BuyOrderSide {
|
||||
isBuying = true
|
||||
}
|
||||
|
||||
if orderType == exchange.LimitOrderType {
|
||||
limitPriceInSettlementCurrency = price
|
||||
if order.OrderType == exchange.LimitOrderType {
|
||||
limitPriceInSettlementCurrency = order.Price
|
||||
}
|
||||
|
||||
response, err := a.NewOrder(orderType.ToString(),
|
||||
response, err := a.NewOrder(order.OrderType.ToString(),
|
||||
isBuying,
|
||||
p.Base.String(),
|
||||
amount,
|
||||
p.Quote.String(),
|
||||
amount,
|
||||
order.Pair.Base.String(),
|
||||
order.Amount,
|
||||
order.Pair.Quote.String(),
|
||||
order.Amount,
|
||||
limitPriceInSettlementCurrency,
|
||||
false,
|
||||
"",
|
||||
|
||||
@@ -402,13 +402,20 @@ func TestSubmitOrder(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var p = currency.Pair{
|
||||
Delimiter: "",
|
||||
Base: currency.LTC,
|
||||
Quote: currency.BTC,
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Delimiter: "_",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USD,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := b.SubmitOrder(p, exchange.BuyOrderSide,
|
||||
exchange.LimitOrderType, 1, 1, "clientId")
|
||||
|
||||
response, err := b.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -312,18 +312,25 @@ func (b *Binance) GetExchangeHistory(p currency.Pair, assetType assets.AssetType
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (b *Binance) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, _ string) (exchange.SubmitOrderResponse, error) {
|
||||
func (b *Binance) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
var sideType string
|
||||
if side == exchange.BuyOrderSide {
|
||||
if order.OrderSide == exchange.BuyOrderSide {
|
||||
sideType = exchange.BuyOrderSide.ToString()
|
||||
} else {
|
||||
sideType = exchange.SellOrderSide.ToString()
|
||||
}
|
||||
|
||||
var requestParamsOrderType RequestParamsOrderType
|
||||
switch orderType {
|
||||
switch order.OrderType {
|
||||
case exchange.MarketOrderType:
|
||||
requestParamsOrderType = BinanceRequestParamsOrderMarket
|
||||
case exchange.LimitOrderType:
|
||||
@@ -334,10 +341,10 @@ func (b *Binance) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderTyp
|
||||
}
|
||||
|
||||
var orderRequest = NewOrderRequest{
|
||||
Symbol: p.Base.String() + p.Quote.String(),
|
||||
Symbol: order.Pair.Base.String() + order.Pair.Quote.String(),
|
||||
Side: sideType,
|
||||
Price: price,
|
||||
Quantity: amount,
|
||||
Price: order.Price,
|
||||
Quantity: order.Amount,
|
||||
TradeType: requestParamsOrderType,
|
||||
TimeInForce: BinanceRequestParamsTimeGTC,
|
||||
}
|
||||
|
||||
@@ -764,12 +764,19 @@ func TestSubmitOrder(t *testing.T) {
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
var p = currency.Pair{
|
||||
Delimiter: "",
|
||||
Base: currency.LTC,
|
||||
Quote: currency.BTC,
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Delimiter: "_",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USD,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := b.SubmitOrder(p, exchange.BuyOrderSide, exchange.LimitOrderType, 1, 1, "clientId")
|
||||
response, err := b.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -295,19 +295,26 @@ func (b *Bitfinex) GetExchangeHistory(p currency.Pair, assetType assets.AssetTyp
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (b *Bitfinex) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, _ string) (exchange.SubmitOrderResponse, error) {
|
||||
func (b *Bitfinex) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
var isBuying bool
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
if side == exchange.BuyOrderSide {
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
var isBuying bool
|
||||
if order.OrderSide == exchange.BuyOrderSide {
|
||||
isBuying = true
|
||||
}
|
||||
|
||||
response, err := b.NewOrder(p.String(),
|
||||
amount,
|
||||
price,
|
||||
response, err := b.NewOrder(order.Pair.String(),
|
||||
order.Amount,
|
||||
order.Price,
|
||||
isBuying,
|
||||
orderType.ToString(),
|
||||
order.OrderType.ToString(),
|
||||
false)
|
||||
|
||||
if response.OrderID > 0 {
|
||||
|
||||
@@ -303,12 +303,18 @@ func TestSubmitOrder(t *testing.T) {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var p = currency.Pair{
|
||||
Delimiter: "",
|
||||
Base: currency.LTC,
|
||||
Quote: currency.BTC,
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Base: currency.BTC,
|
||||
Quote: currency.LTC,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
_, err := b.SubmitOrder(p, exchange.BuyOrderSide, exchange.LimitOrderType, 1, 1, "clientId")
|
||||
_, err := b.SubmitOrder(orderSubmission)
|
||||
if err != common.ErrNotYetImplemented {
|
||||
t.Errorf("Expected 'Not Yet Implemented', received %v", err)
|
||||
}
|
||||
|
||||
@@ -277,10 +277,8 @@ func (b *Bitflyer) GetExchangeHistory(p currency.Pair, assetType assets.AssetTyp
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (b *Bitflyer) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, clientID string) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
|
||||
return submitOrderResponse, common.ErrNotYetImplemented
|
||||
func (b *Bitflyer) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
return exchange.SubmitOrderResponse{}, common.ErrNotYetImplemented
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
|
||||
@@ -345,12 +345,18 @@ func TestSubmitOrder(t *testing.T) {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var p = currency.Pair{
|
||||
Delimiter: "",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.LTC,
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Base: currency.BTC,
|
||||
Quote: currency.LTC,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := b.SubmitOrder(p, exchange.BuyOrderSide, exchange.LimitOrderType, 1, 1, "clientId")
|
||||
response, err := b.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -272,28 +272,34 @@ func (b *Bithumb) GetExchangeHistory(p currency.Pair, assetType assets.AssetType
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
// TODO: Fill this out to support limit orders
|
||||
func (b *Bithumb) SubmitOrder(p currency.Pair, side exchange.OrderSide, _ exchange.OrderType, amount, _ float64, _ string) (exchange.SubmitOrderResponse, error) {
|
||||
func (b *Bithumb) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
var err error
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
var orderID string
|
||||
if side == exchange.BuyOrderSide {
|
||||
var err error
|
||||
if order.OrderSide == exchange.BuyOrderSide {
|
||||
var result MarketBuy
|
||||
result, err = b.MarketBuyOrder(p.Base.String(), amount)
|
||||
result, err = b.MarketBuyOrder(order.Pair.Base.String(), order.Amount)
|
||||
orderID = result.OrderID
|
||||
} else if side == exchange.SellOrderSide {
|
||||
} else if order.OrderSide == exchange.SellOrderSide {
|
||||
var result MarketSell
|
||||
result, err = b.MarketSellOrder(p.Base.String(), amount)
|
||||
result, err = b.MarketSellOrder(order.Pair.Base.String(), order.Amount)
|
||||
orderID = result.OrderID
|
||||
}
|
||||
|
||||
if orderID != "" {
|
||||
submitOrderResponse.OrderID = fmt.Sprintf("%v", orderID)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
}
|
||||
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
|
||||
@@ -516,12 +516,18 @@ func TestSubmitOrder(t *testing.T) {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var p = currency.Pair{
|
||||
Delimiter: "",
|
||||
Base: currency.XBT,
|
||||
Quote: currency.USD,
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Base: currency.XBT,
|
||||
Quote: currency.USD,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := b.SubmitOrder(p, exchange.BuyOrderSide, exchange.LimitOrderType, 1, 1, "clientId")
|
||||
response, err := b.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -343,23 +343,30 @@ func (b *Bitmex) GetExchangeHistory(p currency.Pair, assetType assets.AssetType)
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (b *Bitmex) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, _ string) (exchange.SubmitOrderResponse, error) {
|
||||
func (b *Bitmex) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
if math.Mod(amount, 1) != 0 {
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
if math.Mod(order.Amount, 1) != 0 {
|
||||
return submitOrderResponse,
|
||||
errors.New("contract amount can not have decimals")
|
||||
errors.New("order contract amount can not have decimals")
|
||||
}
|
||||
|
||||
var orderNewParams = OrderNewParams{
|
||||
OrdType: side.ToString(),
|
||||
Symbol: p.String(),
|
||||
OrderQty: amount,
|
||||
Side: side.ToString(),
|
||||
OrdType: order.OrderSide.ToString(),
|
||||
Symbol: order.Pair.String(),
|
||||
OrderQty: order.Amount,
|
||||
Side: order.OrderSide.ToString(),
|
||||
}
|
||||
|
||||
if orderType == exchange.LimitOrderType {
|
||||
orderNewParams.Price = price
|
||||
if order.OrderType == exchange.LimitOrderType {
|
||||
orderNewParams.Price = order.Price
|
||||
}
|
||||
|
||||
response, err := b.CreateOrder(&orderNewParams)
|
||||
|
||||
@@ -417,13 +417,18 @@ func TestSubmitOrder(t *testing.T) {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var p = currency.Pair{
|
||||
Delimiter: "",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USD,
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USD,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := b.SubmitOrder(p,
|
||||
exchange.BuyOrderSide, exchange.LimitOrderType, 1, 1, "clientId")
|
||||
response, err := b.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -308,11 +308,20 @@ func (b *Bitstamp) GetExchangeHistory(p currency.Pair, assetType assets.AssetTyp
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (b *Bitstamp) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, _ string) (exchange.SubmitOrderResponse, error) {
|
||||
func (b *Bitstamp) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
buy := side == exchange.BuyOrderSide
|
||||
market := orderType == exchange.MarketOrderType
|
||||
response, err := b.PlaceOrder(p.String(), price, amount, buy, market)
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
buy := order.OrderSide == exchange.BuyOrderSide
|
||||
market := order.OrderType == exchange.MarketOrderType
|
||||
response, err := b.PlaceOrder(order.Pair.String(), order.Price, order.Amount,
|
||||
buy, market)
|
||||
|
||||
if response.ID > 0 {
|
||||
submitOrderResponse.OrderID = fmt.Sprintf("%v", response.ID)
|
||||
|
||||
@@ -373,12 +373,19 @@ func TestSubmitOrder(t *testing.T) {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var p = currency.Pair{
|
||||
Delimiter: "-",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.LTC,
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Delimiter: "-",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.LTC,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := b.SubmitOrder(p, exchange.BuyOrderSide, exchange.LimitOrderType, 1, 1, "clientId")
|
||||
response, err := b.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -288,20 +288,30 @@ func (b *Bittrex) GetExchangeHistory(p currency.Pair, assetType assets.AssetType
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (b *Bittrex) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, _ string) (exchange.SubmitOrderResponse, error) {
|
||||
func (b *Bittrex) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
buy := side == exchange.BuyOrderSide
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
buy := order.OrderSide == exchange.BuyOrderSide
|
||||
var response UUID
|
||||
var err error
|
||||
|
||||
if orderType != exchange.LimitOrderType {
|
||||
return submitOrderResponse, errors.New("not supported on exchange")
|
||||
if order.OrderType != exchange.LimitOrderType {
|
||||
return submitOrderResponse, errors.New("limit order not supported on exchange")
|
||||
}
|
||||
|
||||
if buy {
|
||||
response, err = b.PlaceBuyLimit(p.String(), amount, price)
|
||||
response, err = b.PlaceBuyLimit(order.Pair.String(), order.Amount,
|
||||
order.Price)
|
||||
} else {
|
||||
response, err = b.PlaceSellLimit(p.String(), amount, price)
|
||||
response, err = b.PlaceSellLimit(order.Pair.String(), order.Amount,
|
||||
order.Price)
|
||||
}
|
||||
|
||||
if response.Result.ID != "" {
|
||||
|
||||
@@ -332,12 +332,19 @@ func TestSubmitOrder(t *testing.T) {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var p = currency.Pair{
|
||||
Delimiter: "-",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.LTC,
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Delimiter: "-",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.LTC,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := b.SubmitOrder(p, exchange.BuyOrderSide, exchange.LimitOrderType, 1, 1, "clientId")
|
||||
response, err := b.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -273,15 +273,30 @@ func (b *BTCMarkets) GetExchangeHistory(p currency.Pair, assetType assets.AssetT
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (b *BTCMarkets) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, clientID string) (exchange.SubmitOrderResponse, error) {
|
||||
func (b *BTCMarkets) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
response, err := b.NewOrder(p.Base.Upper().String(),
|
||||
p.Quote.Upper().String(),
|
||||
price,
|
||||
amount,
|
||||
side.ToString(),
|
||||
orderType.ToString(),
|
||||
clientID)
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
if strings.EqualFold(order.OrderSide.ToString(), exchange.SellOrderSide.ToString()) {
|
||||
order.OrderSide = exchange.AskOrderSide
|
||||
}
|
||||
if strings.EqualFold(order.OrderSide.ToString(), exchange.BuyOrderSide.ToString()) {
|
||||
order.OrderSide = exchange.BuyOrderSide
|
||||
}
|
||||
|
||||
response, err := b.NewOrder(order.Pair.Base.Upper().String(),
|
||||
order.Pair.Quote.Upper().String(),
|
||||
order.Price,
|
||||
order.Amount,
|
||||
order.OrderSide.ToString(),
|
||||
order.OrderType.ToString(),
|
||||
order.ClientID)
|
||||
|
||||
if response > 0 {
|
||||
submitOrderResponse.OrderID = fmt.Sprintf("%v", response)
|
||||
|
||||
@@ -242,12 +242,18 @@ func TestSubmitOrder(t *testing.T) {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var p = currency.Pair{
|
||||
Delimiter: "",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USD,
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USD,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := b.SubmitOrder(p, exchange.SellOrderSide, exchange.LimitOrderType, 0.01, 1000000, "clientId")
|
||||
response, err := b.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -260,11 +260,19 @@ func (b *BTSE) GetExchangeHistory(p currency.Pair, assetType assets.AssetType) (
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (b *BTSE) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, clientID string) (exchange.SubmitOrderResponse, error) {
|
||||
func (b *BTSE) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var resp exchange.SubmitOrderResponse
|
||||
r, err := b.CreateOrder(amount, price, side.ToString(),
|
||||
orderType.ToString(), b.FormatExchangeCurrency(p,
|
||||
assets.AssetTypeSpot).String(), "GTC", clientID)
|
||||
if order == nil {
|
||||
return resp, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
if err := order.Validate(); err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
r, err := b.CreateOrder(order.Amount, order.Price, order.OrderSide.ToString(),
|
||||
order.OrderType.ToString(), b.FormatExchangeCurrency(order.Pair,
|
||||
assets.AssetTypeSpot).String(), "GTC", order.ClientID)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
@@ -470,13 +470,19 @@ func TestSubmitOrder(t *testing.T) {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var p = currency.Pair{
|
||||
Delimiter: "-",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.LTC,
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Delimiter: "-",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USD,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := c.SubmitOrder(p, exchange.BuyOrderSide,
|
||||
exchange.LimitOrderType, 1, 1, "clientId")
|
||||
response, err := c.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -285,27 +285,34 @@ func (c *CoinbasePro) GetExchangeHistory(p currency.Pair, assetType assets.Asset
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (c *CoinbasePro) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, _ string) (exchange.SubmitOrderResponse, error) {
|
||||
func (c *CoinbasePro) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
var response string
|
||||
var err error
|
||||
|
||||
switch orderType {
|
||||
switch order.OrderType {
|
||||
case exchange.MarketOrderType:
|
||||
response, err = c.PlaceMarginOrder("",
|
||||
amount,
|
||||
amount,
|
||||
side.ToString(),
|
||||
p.String(),
|
||||
response, err = c.PlaceMarketOrder("",
|
||||
order.Amount,
|
||||
order.Amount,
|
||||
order.OrderSide.ToString(),
|
||||
order.Pair.String(),
|
||||
"")
|
||||
case exchange.LimitOrderType:
|
||||
response, err = c.PlaceLimitOrder("",
|
||||
price,
|
||||
amount,
|
||||
side.ToString(),
|
||||
order.Price,
|
||||
order.Amount,
|
||||
order.OrderSide.ToString(),
|
||||
"",
|
||||
"",
|
||||
p.String(),
|
||||
order.Pair.String(),
|
||||
"",
|
||||
false)
|
||||
default:
|
||||
|
||||
@@ -246,12 +246,18 @@ func TestSubmitOrder(t *testing.T) {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var p = currency.Pair{
|
||||
Delimiter: "",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USD,
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USD,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := c.SubmitOrder(p, exchange.BuyOrderSide, exchange.LimitOrderType, 1, 10, "1234234")
|
||||
response, err := c.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package coinut
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -328,33 +327,41 @@ func (c *COINUT) GetExchangeHistory(p currency.Pair, assetType assets.AssetType)
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (c *COINUT) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, clientID string) (exchange.SubmitOrderResponse, error) {
|
||||
func (c *COINUT) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
var err error
|
||||
var APIresponse interface{}
|
||||
isBuyOrder := side == exchange.BuyOrderSide
|
||||
clientIDInt, err := strconv.ParseUint(clientID, 0, 32)
|
||||
clientIDUint := uint32(clientIDInt)
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
var APIresponse interface{}
|
||||
isBuyOrder := order.OrderSide == exchange.BuyOrderSide
|
||||
clientIDInt, err := strconv.ParseUint(order.ClientID, 0, 32)
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
clientIDUint := uint32(clientIDInt)
|
||||
|
||||
// Need to get the ID of the currency sent
|
||||
instruments, err := c.GetInstruments()
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
currencyArray := instruments.Instruments[p.String()]
|
||||
currencyArray := instruments.Instruments[order.Pair.String()]
|
||||
currencyID := currencyArray[0].InstID
|
||||
|
||||
switch orderType {
|
||||
switch order.OrderType {
|
||||
case exchange.LimitOrderType:
|
||||
APIresponse, err = c.NewOrder(currencyID, amount, price, isBuyOrder, clientIDUint)
|
||||
APIresponse, err = c.NewOrder(currencyID, order.Amount, order.Price,
|
||||
isBuyOrder, clientIDUint)
|
||||
case exchange.MarketOrderType:
|
||||
APIresponse, err = c.NewOrder(currencyID, amount, 0, isBuyOrder, clientIDUint)
|
||||
default:
|
||||
return submitOrderResponse, errors.New("unsupported order type")
|
||||
APIresponse, err = c.NewOrder(currencyID, order.Amount, 0, isBuyOrder,
|
||||
clientIDUint)
|
||||
}
|
||||
|
||||
switch apiResp := APIresponse.(type) {
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
package exchange
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/assets"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
)
|
||||
|
||||
@@ -51,12 +47,6 @@ const (
|
||||
Contact
|
||||
)
|
||||
|
||||
// SubmitOrderResponse is what is returned after submitting an order to an exchange
|
||||
type SubmitOrderResponse struct {
|
||||
IsOrderPlaced bool
|
||||
OrderID string
|
||||
}
|
||||
|
||||
// FeeBuilder is the type which holds all parameters required to calculate a fee
|
||||
// for an exchange
|
||||
type FeeBuilder struct {
|
||||
@@ -119,80 +109,6 @@ const (
|
||||
UnknownWithdrawalTypeText string = "UNKNOWN"
|
||||
)
|
||||
|
||||
// ModifyOrder is a an order modifyer
|
||||
// ModifyOrder is a an order modifyer
|
||||
type ModifyOrder struct {
|
||||
OrderID string
|
||||
OrderType
|
||||
OrderSide
|
||||
Price float64
|
||||
Amount float64
|
||||
LimitPriceUpper float64
|
||||
LimitPriceLower float64
|
||||
CurrencyPair currency.Pair
|
||||
|
||||
ImmediateOrCancel bool
|
||||
HiddenOrder bool
|
||||
FillOrKill bool
|
||||
PostOnly bool
|
||||
}
|
||||
|
||||
// ModifyOrderResponse is an order modifying return type
|
||||
type ModifyOrderResponse struct {
|
||||
OrderID string
|
||||
}
|
||||
|
||||
// CancelAllOrdersResponse returns the status from attempting to cancel all orders on an exchagne
|
||||
type CancelAllOrdersResponse struct {
|
||||
OrderStatus map[string]string
|
||||
}
|
||||
|
||||
// OrderType enforces a standard for Ordertypes across the code base
|
||||
type OrderType string
|
||||
|
||||
// OrderType ...types
|
||||
const (
|
||||
AnyOrderType OrderType = "ANY"
|
||||
LimitOrderType OrderType = "LIMIT"
|
||||
MarketOrderType OrderType = "MARKET"
|
||||
ImmediateOrCancelOrderType OrderType = "IMMEDIATE_OR_CANCEL"
|
||||
StopOrderType OrderType = "STOP"
|
||||
TrailingStopOrderType OrderType = "TRAILINGSTOP"
|
||||
UnknownOrderType OrderType = "UNKNOWN"
|
||||
)
|
||||
|
||||
// ToLower changes the ordertype to lower case
|
||||
func (o OrderType) ToLower() OrderType {
|
||||
return OrderType(strings.ToLower(string(o)))
|
||||
}
|
||||
|
||||
// ToString changes the ordertype to the exchange standard and returns a string
|
||||
func (o OrderType) ToString() string {
|
||||
return fmt.Sprintf("%v", o)
|
||||
}
|
||||
|
||||
// OrderSide enforces a standard for OrderSides across the code base
|
||||
type OrderSide string
|
||||
|
||||
// OrderSide types
|
||||
const (
|
||||
AnyOrderSide OrderSide = "ANY"
|
||||
BuyOrderSide OrderSide = "BUY"
|
||||
SellOrderSide OrderSide = "SELL"
|
||||
BidOrderSide OrderSide = "BID"
|
||||
AskOrderSide OrderSide = "ASK"
|
||||
)
|
||||
|
||||
// ToLower changes the ordertype to lower case
|
||||
func (o OrderSide) ToLower() OrderSide {
|
||||
return OrderSide(strings.ToLower(string(o)))
|
||||
}
|
||||
|
||||
// ToString changes the ordertype to the exchange standard and returns a string
|
||||
func (o OrderSide) ToString() string {
|
||||
return fmt.Sprintf("%v", o)
|
||||
}
|
||||
|
||||
// AccountInfo is a Generic type to hold each exchange's holdings in
|
||||
// all enabled currencies
|
||||
type AccountInfo struct {
|
||||
@@ -225,34 +141,6 @@ type TradeHistory struct {
|
||||
Description string
|
||||
}
|
||||
|
||||
// OrderDetail holds order detail data
|
||||
type OrderDetail struct {
|
||||
Exchange string
|
||||
AccountID string
|
||||
ID string
|
||||
CurrencyPair currency.Pair
|
||||
OrderSide OrderSide
|
||||
OrderType OrderType
|
||||
OrderDate time.Time
|
||||
Status string
|
||||
Price float64
|
||||
Amount float64
|
||||
ExecutedAmount float64
|
||||
RemainingAmount float64
|
||||
Fee float64
|
||||
Trades []TradeHistory
|
||||
}
|
||||
|
||||
// OrderCancellation type required when requesting to cancel an order
|
||||
type OrderCancellation struct {
|
||||
AccountID string
|
||||
OrderID string
|
||||
CurrencyPair currency.Pair
|
||||
AssetType assets.AssetType
|
||||
WalletAddress string
|
||||
Side OrderSide
|
||||
}
|
||||
|
||||
// FundHistory holds exchange funding history data
|
||||
type FundHistory struct {
|
||||
ExchangeName string
|
||||
@@ -402,227 +290,6 @@ type API struct {
|
||||
}
|
||||
}
|
||||
|
||||
// GetOrdersRequest used for GetOrderHistory and GetOpenOrders wrapper functions
|
||||
type GetOrdersRequest struct {
|
||||
OrderType OrderType
|
||||
OrderSide OrderSide
|
||||
StartTicks time.Time
|
||||
EndTicks time.Time
|
||||
// Currencies Empty array = all currencies. Some endpoints only support singular currency enquiries
|
||||
Currencies []currency.Pair
|
||||
}
|
||||
|
||||
// OrderStatus defines order status types
|
||||
type OrderStatus string
|
||||
|
||||
// All OrderStatus types
|
||||
const (
|
||||
AnyOrderStatus OrderStatus = "ANY"
|
||||
NewOrderStatus OrderStatus = "NEW"
|
||||
ActiveOrderStatus OrderStatus = "ACTIVE"
|
||||
PartiallyFilledOrderStatus OrderStatus = "PARTIALLY_FILLED"
|
||||
FilledOrderStatus OrderStatus = "FILLED"
|
||||
CancelledOrderStatus OrderStatus = "CANCELED"
|
||||
PendingCancelOrderStatus OrderStatus = "PENDING_CANCEL"
|
||||
RejectedOrderStatus OrderStatus = "REJECTED"
|
||||
ExpiredOrderStatus OrderStatus = "EXPIRED"
|
||||
HiddenOrderStatus OrderStatus = "HIDDEN"
|
||||
UnknownOrderStatus OrderStatus = "UNKNOWN"
|
||||
)
|
||||
|
||||
// FilterOrdersBySide removes any OrderDetails that don't match the orderStatus provided
|
||||
func FilterOrdersBySide(orders *[]OrderDetail, orderSide OrderSide) {
|
||||
if orderSide == "" || orderSide == AnyOrderSide {
|
||||
return
|
||||
}
|
||||
|
||||
var filteredOrders []OrderDetail
|
||||
for i := range *orders {
|
||||
if strings.EqualFold(string((*orders)[i].OrderSide), string(orderSide)) {
|
||||
filteredOrders = append(filteredOrders, (*orders)[i])
|
||||
}
|
||||
}
|
||||
|
||||
*orders = filteredOrders
|
||||
}
|
||||
|
||||
// FilterOrdersByType removes any OrderDetails that don't match the orderType provided
|
||||
func FilterOrdersByType(orders *[]OrderDetail, orderType OrderType) {
|
||||
if orderType == "" || orderType == AnyOrderType {
|
||||
return
|
||||
}
|
||||
|
||||
var filteredOrders []OrderDetail
|
||||
for i := range *orders {
|
||||
if strings.EqualFold(string((*orders)[i].OrderType), string(orderType)) {
|
||||
filteredOrders = append(filteredOrders, (*orders)[i])
|
||||
}
|
||||
}
|
||||
|
||||
*orders = filteredOrders
|
||||
}
|
||||
|
||||
// FilterOrdersByTickRange removes any OrderDetails outside of the tick range
|
||||
func FilterOrdersByTickRange(orders *[]OrderDetail, startTicks, endTicks time.Time) {
|
||||
if startTicks.IsZero() || endTicks.IsZero() ||
|
||||
startTicks.Unix() == 0 || endTicks.Unix() == 0 || endTicks.Before(startTicks) {
|
||||
return
|
||||
}
|
||||
|
||||
var filteredOrders []OrderDetail
|
||||
for i := range *orders {
|
||||
if (*orders)[i].OrderDate.Unix() >= startTicks.Unix() && (*orders)[i].OrderDate.Unix() <= endTicks.Unix() {
|
||||
filteredOrders = append(filteredOrders, (*orders)[i])
|
||||
}
|
||||
}
|
||||
|
||||
*orders = filteredOrders
|
||||
}
|
||||
|
||||
// FilterOrdersByCurrencies removes any OrderDetails that do not match the provided currency list
|
||||
// It is forgiving in that the provided currencies can match quote or base currencies
|
||||
func FilterOrdersByCurrencies(orders *[]OrderDetail, currencies []currency.Pair) {
|
||||
if len(currencies) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var filteredOrders []OrderDetail
|
||||
for i := range *orders {
|
||||
matchFound := false
|
||||
for _, c := range currencies {
|
||||
if !matchFound && (*orders)[i].CurrencyPair.EqualIncludeReciprocal(c) {
|
||||
matchFound = true
|
||||
}
|
||||
}
|
||||
|
||||
if matchFound {
|
||||
filteredOrders = append(filteredOrders, (*orders)[i])
|
||||
}
|
||||
}
|
||||
|
||||
*orders = filteredOrders
|
||||
}
|
||||
|
||||
// ByPrice used for sorting orders by price
|
||||
type ByPrice []OrderDetail
|
||||
|
||||
func (b ByPrice) Len() int {
|
||||
return len(b)
|
||||
}
|
||||
|
||||
func (b ByPrice) Less(i, j int) bool {
|
||||
return b[i].Price < b[j].Price
|
||||
}
|
||||
|
||||
func (b ByPrice) Swap(i, j int) {
|
||||
b[i], b[j] = b[j], b[i]
|
||||
}
|
||||
|
||||
// SortOrdersByPrice the caller function to sort orders
|
||||
func SortOrdersByPrice(orders *[]OrderDetail, reverse bool) {
|
||||
if reverse {
|
||||
sort.Sort(sort.Reverse(ByPrice(*orders)))
|
||||
} else {
|
||||
sort.Sort(ByPrice(*orders))
|
||||
}
|
||||
}
|
||||
|
||||
// ByOrderType used for sorting orders by order type
|
||||
type ByOrderType []OrderDetail
|
||||
|
||||
func (b ByOrderType) Len() int {
|
||||
return len(b)
|
||||
}
|
||||
|
||||
func (b ByOrderType) Less(i, j int) bool {
|
||||
return b[i].OrderType.ToString() < b[j].OrderType.ToString()
|
||||
}
|
||||
|
||||
func (b ByOrderType) Swap(i, j int) {
|
||||
b[i], b[j] = b[j], b[i]
|
||||
}
|
||||
|
||||
// SortOrdersByType the caller function to sort orders
|
||||
func SortOrdersByType(orders *[]OrderDetail, reverse bool) {
|
||||
if reverse {
|
||||
sort.Sort(sort.Reverse(ByOrderType(*orders)))
|
||||
} else {
|
||||
sort.Sort(ByOrderType(*orders))
|
||||
}
|
||||
}
|
||||
|
||||
// ByCurrency used for sorting orders by order currency
|
||||
type ByCurrency []OrderDetail
|
||||
|
||||
func (b ByCurrency) Len() int {
|
||||
return len(b)
|
||||
}
|
||||
|
||||
func (b ByCurrency) Less(i, j int) bool {
|
||||
return b[i].CurrencyPair.String() < b[j].CurrencyPair.String()
|
||||
}
|
||||
|
||||
func (b ByCurrency) Swap(i, j int) {
|
||||
b[i], b[j] = b[j], b[i]
|
||||
}
|
||||
|
||||
// SortOrdersByCurrency the caller function to sort orders
|
||||
func SortOrdersByCurrency(orders *[]OrderDetail, reverse bool) {
|
||||
if reverse {
|
||||
sort.Sort(sort.Reverse(ByCurrency(*orders)))
|
||||
} else {
|
||||
sort.Sort(ByCurrency(*orders))
|
||||
}
|
||||
}
|
||||
|
||||
// ByDate used for sorting orders by order date
|
||||
type ByDate []OrderDetail
|
||||
|
||||
func (b ByDate) Len() int {
|
||||
return len(b)
|
||||
}
|
||||
|
||||
func (b ByDate) Less(i, j int) bool {
|
||||
return b[i].OrderDate.Unix() < b[j].OrderDate.Unix()
|
||||
}
|
||||
|
||||
func (b ByDate) Swap(i, j int) {
|
||||
b[i], b[j] = b[j], b[i]
|
||||
}
|
||||
|
||||
// SortOrdersByDate the caller function to sort orders
|
||||
func SortOrdersByDate(orders *[]OrderDetail, reverse bool) {
|
||||
if reverse {
|
||||
sort.Sort(sort.Reverse(ByDate(*orders)))
|
||||
} else {
|
||||
sort.Sort(ByDate(*orders))
|
||||
}
|
||||
}
|
||||
|
||||
// ByOrderSide used for sorting orders by order side (buy sell)
|
||||
type ByOrderSide []OrderDetail
|
||||
|
||||
func (b ByOrderSide) Len() int {
|
||||
return len(b)
|
||||
}
|
||||
|
||||
func (b ByOrderSide) Less(i, j int) bool {
|
||||
return b[i].OrderSide.ToString() < b[j].OrderSide.ToString()
|
||||
}
|
||||
|
||||
func (b ByOrderSide) Swap(i, j int) {
|
||||
b[i], b[j] = b[j], b[i]
|
||||
}
|
||||
|
||||
// SortOrdersBySide the caller function to sort orders
|
||||
func SortOrdersBySide(orders *[]OrderDetail, reverse bool) {
|
||||
if reverse {
|
||||
sort.Sort(sort.Reverse(ByOrderSide(*orders)))
|
||||
} else {
|
||||
sort.Sort(ByOrderSide(*orders))
|
||||
}
|
||||
}
|
||||
|
||||
// Base stores the individual exchange information
|
||||
type Base struct {
|
||||
Name string
|
||||
|
||||
@@ -306,13 +306,19 @@ func TestSubmitOrder(t *testing.T) {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var p = currency.Pair{
|
||||
Delimiter: "_",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USD,
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Delimiter: "_",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USD,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := e.SubmitOrder(p, exchange.BuyOrderSide,
|
||||
exchange.LimitOrderType, 1, 10, "1234234")
|
||||
response, err := e.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -298,24 +298,29 @@ func (e *EXMO) GetExchangeHistory(p currency.Pair, assetType assets.AssetType) (
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (e *EXMO) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, _ string) (exchange.SubmitOrderResponse, error) {
|
||||
func (e *EXMO) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
var oT string
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
switch orderType {
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
var oT string
|
||||
switch order.OrderType {
|
||||
case exchange.LimitOrderType:
|
||||
return submitOrderResponse, errors.New("unsupported order type")
|
||||
case exchange.MarketOrderType:
|
||||
oT = "market_buy"
|
||||
if side == exchange.SellOrderSide {
|
||||
if order.OrderSide == exchange.SellOrderSide {
|
||||
oT = "market_sell"
|
||||
}
|
||||
default:
|
||||
return submitOrderResponse, errors.New("unsupported order type")
|
||||
}
|
||||
|
||||
response, err := e.CreateOrder(p.String(), oT, price, amount)
|
||||
|
||||
response, err := e.CreateOrder(order.Pair.String(), oT, order.Price,
|
||||
order.Amount)
|
||||
if response > 0 {
|
||||
submitOrderResponse.OrderID = fmt.Sprintf("%v", response)
|
||||
}
|
||||
|
||||
@@ -312,13 +312,19 @@ func TestSubmitOrder(t *testing.T) {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
var p = currency.Pair{
|
||||
Delimiter: "_",
|
||||
Base: currency.LTC,
|
||||
Quote: currency.BTC,
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Delimiter: "_",
|
||||
Base: currency.LTC,
|
||||
Quote: currency.BTC,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := g.SubmitOrder(p, exchange.BuyOrderSide,
|
||||
exchange.LimitOrderType, 1, 10, "1234234")
|
||||
response, err := g.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -318,25 +318,31 @@ func (g *Gateio) GetExchangeHistory(p currency.Pair, assetType assets.AssetType)
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
// TODO: support multiple order types (IOC)
|
||||
func (g *Gateio) SubmitOrder(p currency.Pair, side exchange.OrderSide, _ exchange.OrderType, amount, price float64, _ string) (exchange.SubmitOrderResponse, error) {
|
||||
func (g *Gateio) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
var orderTypeFormat string
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
if side == exchange.BuyOrderSide {
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
var orderTypeFormat string
|
||||
if order.OrderSide == exchange.BuyOrderSide {
|
||||
orderTypeFormat = exchange.BuyOrderSide.ToLower().ToString()
|
||||
} else {
|
||||
orderTypeFormat = exchange.SellOrderSide.ToLower().ToString()
|
||||
}
|
||||
|
||||
var spotNewOrderRequestParams = SpotNewOrderRequestParams{
|
||||
Amount: amount,
|
||||
Price: price,
|
||||
Symbol: p.String(),
|
||||
Amount: order.Amount,
|
||||
Price: order.Price,
|
||||
Symbol: order.Pair.String(),
|
||||
Type: orderTypeFormat,
|
||||
}
|
||||
|
||||
response, err := g.SpotNewOrder(spotNewOrderRequestParams)
|
||||
|
||||
if response.OrderNumber > 0 {
|
||||
submitOrderResponse.OrderID = fmt.Sprintf("%v", response.OrderNumber)
|
||||
}
|
||||
|
||||
@@ -409,13 +409,19 @@ func TestSubmitOrder(t *testing.T) {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var p = currency.Pair{
|
||||
Delimiter: "_",
|
||||
Base: currency.LTC,
|
||||
Quote: currency.BTC,
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Delimiter: "_",
|
||||
Base: currency.LTC,
|
||||
Quote: currency.BTC,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := Session[1].SubmitOrder(p, exchange.BuyOrderSide,
|
||||
exchange.LimitOrderType, 1, 10, "1234234")
|
||||
response, err := Session[1].SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -266,22 +266,27 @@ func (g *Gemini) GetExchangeHistory(p currency.Pair, assetType assets.AssetType)
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (g *Gemini) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, _ string) (exchange.SubmitOrderResponse, error) {
|
||||
func (g *Gemini) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
response, err := g.NewOrder(p.String(),
|
||||
amount,
|
||||
price,
|
||||
side.ToString(),
|
||||
orderType.ToString())
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
response, err := g.NewOrder(order.Pair.String(),
|
||||
order.Amount,
|
||||
order.Price,
|
||||
order.OrderSide.ToString(),
|
||||
order.OrderType.ToString())
|
||||
if response > 0 {
|
||||
submitOrderResponse.OrderID = fmt.Sprintf("%v", response)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
}
|
||||
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
|
||||
@@ -232,13 +232,18 @@ func TestSubmitOrder(t *testing.T) {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var p = currency.Pair{
|
||||
Delimiter: "",
|
||||
Base: currency.DGD,
|
||||
Quote: currency.BTC,
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Base: currency.DGD,
|
||||
Quote: currency.BTC,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := h.SubmitOrder(p, exchange.BuyOrderSide,
|
||||
exchange.LimitOrderType, 1, 10, "1234234")
|
||||
response, err := h.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -291,22 +291,27 @@ func (h *HitBTC) GetExchangeHistory(p currency.Pair, assetType assets.AssetType)
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (h *HitBTC) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, _ string) (exchange.SubmitOrderResponse, error) {
|
||||
func (h *HitBTC) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
response, err := h.PlaceOrder(p.String(),
|
||||
price,
|
||||
amount,
|
||||
strings.ToLower(orderType.ToString()),
|
||||
strings.ToLower(side.ToString()))
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
response, err := h.PlaceOrder(order.Pair.String(),
|
||||
order.Price,
|
||||
order.Amount,
|
||||
strings.ToLower(order.OrderType.ToString()),
|
||||
strings.ToLower(order.OrderSide.ToString()))
|
||||
if response.OrderNumber > 0 {
|
||||
submitOrderResponse.OrderID = fmt.Sprintf("%v", response.OrderNumber)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
}
|
||||
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
|
||||
@@ -432,18 +432,23 @@ func TestSubmitOrder(t *testing.T) {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var p = currency.Pair{
|
||||
Delimiter: "",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USDT,
|
||||
}
|
||||
|
||||
accounts, err := h.GetAccounts()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get accounts. Err: %s", err)
|
||||
}
|
||||
|
||||
response, err := h.SubmitOrder(p, exchange.BuyOrderSide, exchange.LimitOrderType, 1, 10, strconv.FormatInt(accounts[0].ID, 10))
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USDT,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: strconv.FormatInt(accounts[0].ID, 10),
|
||||
}
|
||||
response, err := h.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
}
|
||||
|
||||
@@ -379,34 +379,40 @@ func (h *HUOBI) GetExchangeHistory(p currency.Pair, assetType assets.AssetType)
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (h *HUOBI) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, clientID string) (exchange.SubmitOrderResponse, error) {
|
||||
func (h *HUOBI) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
accountID, err := strconv.ParseInt(clientID, 10, 64)
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
accountID, err := strconv.ParseInt(order.ClientID, 10, 64)
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
var formattedType SpotNewOrderRequestParamsType
|
||||
var params = SpotNewOrderRequestParams{
|
||||
Amount: amount,
|
||||
Amount: order.Amount,
|
||||
Source: "api",
|
||||
Symbol: strings.ToLower(p.String()),
|
||||
Symbol: strings.ToLower(order.Pair.String()),
|
||||
AccountID: int(accountID),
|
||||
}
|
||||
|
||||
switch {
|
||||
case side == exchange.BuyOrderSide && orderType == exchange.MarketOrderType:
|
||||
case order.OrderSide == exchange.BuyOrderSide && order.OrderType == exchange.MarketOrderType:
|
||||
formattedType = SpotNewOrderRequestTypeBuyMarket
|
||||
case side == exchange.SellOrderSide && orderType == exchange.MarketOrderType:
|
||||
case order.OrderSide == exchange.SellOrderSide && order.OrderType == exchange.MarketOrderType:
|
||||
formattedType = SpotNewOrderRequestTypeSellMarket
|
||||
case side == exchange.BuyOrderSide && orderType == exchange.LimitOrderType:
|
||||
case order.OrderSide == exchange.BuyOrderSide && order.OrderType == exchange.LimitOrderType:
|
||||
formattedType = SpotNewOrderRequestTypeBuyLimit
|
||||
params.Price = price
|
||||
case side == exchange.SellOrderSide && orderType == exchange.LimitOrderType:
|
||||
params.Price = order.Price
|
||||
case order.OrderSide == exchange.SellOrderSide && order.OrderType == exchange.LimitOrderType:
|
||||
formattedType = SpotNewOrderRequestTypeSellLimit
|
||||
params.Price = price
|
||||
default:
|
||||
return submitOrderResponse, errors.New("unsupported order type")
|
||||
params.Price = order.Price
|
||||
}
|
||||
|
||||
params.Type = formattedType
|
||||
@@ -414,11 +420,9 @@ func (h *HUOBI) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType
|
||||
if response > 0 {
|
||||
submitOrderResponse.OrderID = fmt.Sprintf("%v", response)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
}
|
||||
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
|
||||
@@ -466,18 +466,23 @@ func TestSubmitOrder(t *testing.T) {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
var p = currency.Pair{
|
||||
Delimiter: "",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USDT,
|
||||
}
|
||||
|
||||
accounts, err := h.GetAccounts()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get accounts. Err: %s", err)
|
||||
}
|
||||
|
||||
response, err := h.SubmitOrder(p, exchange.BuyOrderSide, exchange.LimitOrderType, 1, 10, strconv.FormatInt(accounts[0].ID, 10))
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USDT,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: strconv.FormatInt(accounts[0].ID, 10),
|
||||
}
|
||||
response, err := h.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
}
|
||||
|
||||
@@ -340,48 +340,50 @@ func (h *HUOBIHADAX) GetExchangeHistory(p currency.Pair, assetType assets.AssetT
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (h *HUOBIHADAX) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, clientID string) (exchange.SubmitOrderResponse, error) {
|
||||
func (h *HUOBIHADAX) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
accountID, err := strconv.ParseInt(clientID, 0, 64)
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
accountID, err := strconv.ParseInt(order.ClientID, 10, 64)
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
var formattedType SpotNewOrderRequestParamsType
|
||||
var params = SpotNewOrderRequestParams{
|
||||
Amount: amount,
|
||||
Amount: order.Amount,
|
||||
Source: "api",
|
||||
Symbol: strings.ToLower(p.String()),
|
||||
Symbol: strings.ToLower(order.Pair.String()),
|
||||
AccountID: int(accountID),
|
||||
}
|
||||
|
||||
switch {
|
||||
case side == exchange.BuyOrderSide && orderType == exchange.MarketOrderType:
|
||||
case order.OrderSide == exchange.BuyOrderSide && order.OrderType == exchange.MarketOrderType:
|
||||
formattedType = SpotNewOrderRequestTypeBuyMarket
|
||||
case side == exchange.SellOrderSide && orderType == exchange.MarketOrderType:
|
||||
case order.OrderSide == exchange.SellOrderSide && order.OrderType == exchange.MarketOrderType:
|
||||
formattedType = SpotNewOrderRequestTypeSellMarket
|
||||
case side == exchange.BuyOrderSide && orderType == exchange.LimitOrderType:
|
||||
case order.OrderSide == exchange.BuyOrderSide && order.OrderType == exchange.LimitOrderType:
|
||||
formattedType = SpotNewOrderRequestTypeBuyLimit
|
||||
params.Price = price
|
||||
case side == exchange.SellOrderSide && orderType == exchange.LimitOrderType:
|
||||
params.Price = order.Price
|
||||
case order.OrderSide == exchange.SellOrderSide && order.OrderType == exchange.LimitOrderType:
|
||||
formattedType = SpotNewOrderRequestTypeSellLimit
|
||||
params.Price = price
|
||||
default:
|
||||
return submitOrderResponse, errors.New("unsupported order type")
|
||||
params.Price = order.Price
|
||||
}
|
||||
|
||||
params.Type = formattedType
|
||||
|
||||
response, err := h.SpotNewOrder(params)
|
||||
|
||||
if response > 0 {
|
||||
submitOrderResponse.OrderID = fmt.Sprintf("%v", response)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
}
|
||||
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ type IBotExchange interface {
|
||||
FormatWithdrawPermissions() string
|
||||
SupportsWithdrawPermissions(permissions uint32) bool
|
||||
GetFundingHistory() ([]FundHistory, error)
|
||||
SubmitOrder(p currency.Pair, side OrderSide, orderType OrderType, amount, price float64, clientID string) (SubmitOrderResponse, error)
|
||||
SubmitOrder(order *OrderSubmission) (SubmitOrderResponse, error)
|
||||
ModifyOrder(action *ModifyOrder) (string, error)
|
||||
CancelOrder(order *OrderCancellation) error
|
||||
CancelAllOrders(orders *OrderCancellation) (CancelAllOrdersResponse, error)
|
||||
|
||||
@@ -303,12 +303,18 @@ func TestSubmitOrder(t *testing.T) {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var p = currency.Pair{
|
||||
Delimiter: "",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USDT,
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USD,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := i.SubmitOrder(p, exchange.BuyOrderSide, exchange.LimitOrderType, 1, 10, "hi")
|
||||
response, err := i.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -273,10 +273,17 @@ func (i *ItBit) GetExchangeHistory(p currency.Pair, assetType assets.AssetType)
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (i *ItBit) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, _ string) (exchange.SubmitOrderResponse, error) {
|
||||
func (i *ItBit) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
var wallet string
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
var wallet string
|
||||
wallets, err := i.GetWallets(url.Values{})
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
@@ -285,8 +292,8 @@ func (i *ItBit) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType
|
||||
// Determine what wallet ID to use if there is any actual available currency to make the trade!
|
||||
for _, i := range wallets {
|
||||
for j := range i.Balances {
|
||||
if i.Balances[j].Currency == p.Base.String() &&
|
||||
i.Balances[j].AvailableBalance >= amount {
|
||||
if i.Balances[j].Currency == order.Pair.Base.String() &&
|
||||
i.Balances[j].AvailableBalance >= order.Amount {
|
||||
wallet = i.ID
|
||||
}
|
||||
}
|
||||
@@ -295,23 +302,21 @@ func (i *ItBit) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType
|
||||
if wallet == "" {
|
||||
return submitOrderResponse,
|
||||
fmt.Errorf("no wallet found with currency: %s with amount >= %v",
|
||||
p.Base,
|
||||
amount)
|
||||
order.Pair.Base,
|
||||
order.Amount)
|
||||
}
|
||||
|
||||
response, err := i.PlaceOrder(wallet,
|
||||
side.ToString(),
|
||||
orderType.ToString(),
|
||||
p.Base.String(),
|
||||
amount,
|
||||
price,
|
||||
p.String(),
|
||||
order.OrderSide.ToString(),
|
||||
order.OrderType.ToString(),
|
||||
order.Pair.Base.String(),
|
||||
order.Amount,
|
||||
order.Price,
|
||||
order.Pair.String(),
|
||||
"")
|
||||
|
||||
if response.ID != "" {
|
||||
submitOrderResponse.OrderID = response.ID
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
}
|
||||
|
||||
@@ -422,12 +422,18 @@ func TestSubmitOrder(t *testing.T) {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var p = currency.Pair{
|
||||
Delimiter: "",
|
||||
Base: currency.XBT,
|
||||
Quote: currency.CAD,
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Base: currency.XBT,
|
||||
Quote: currency.USD,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := k.SubmitOrder(p, exchange.BuyOrderSide, exchange.LimitOrderType, 1, 10, "hi")
|
||||
response, err := k.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -318,27 +318,31 @@ func (k *Kraken) GetExchangeHistory(p currency.Pair, assetType assets.AssetType)
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (k *Kraken) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, _ string) (exchange.SubmitOrderResponse, error) {
|
||||
func (k *Kraken) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
var args = AddOrderOptions{}
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
response, err := k.AddOrder(p.String(),
|
||||
side.ToString(),
|
||||
orderType.ToString(),
|
||||
amount,
|
||||
price,
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
var args = AddOrderOptions{}
|
||||
response, err := k.AddOrder(order.Pair.String(),
|
||||
order.OrderSide.ToString(),
|
||||
order.OrderType.ToString(),
|
||||
order.Amount,
|
||||
order.Price,
|
||||
0,
|
||||
0,
|
||||
&args)
|
||||
|
||||
if len(response.TransactionIds) > 0 {
|
||||
submitOrderResponse.OrderID = strings.Join(response.TransactionIds, ", ")
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
}
|
||||
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
|
||||
@@ -297,12 +297,18 @@ func TestSubmitOrder(t *testing.T) {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var p = currency.Pair{
|
||||
Delimiter: "",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.EUR,
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Base: currency.BTC,
|
||||
Quote: currency.EUR,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := l.SubmitOrder(p, exchange.BuyOrderSide, exchange.LimitOrderType, 1, 10, "hi")
|
||||
response, err := l.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -266,19 +266,25 @@ func (l *LakeBTC) GetExchangeHistory(p currency.Pair, assetType assets.AssetType
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (l *LakeBTC) SubmitOrder(p currency.Pair, side exchange.OrderSide, _ exchange.OrderType, amount, price float64, _ string) (exchange.SubmitOrderResponse, error) {
|
||||
func (l *LakeBTC) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
isBuyOrder := side == exchange.BuyOrderSide
|
||||
response, err := l.Trade(isBuyOrder, amount, price, p.Lower().String())
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
isBuyOrder := order.OrderSide == exchange.BuyOrderSide
|
||||
response, err := l.Trade(isBuyOrder, order.Amount, order.Price,
|
||||
order.Pair.Lower().String())
|
||||
if response.ID > 0 {
|
||||
submitOrderResponse.OrderID = fmt.Sprintf("%v", response.ID)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
}
|
||||
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
|
||||
@@ -256,12 +256,18 @@ func TestSubmitOrder(t *testing.T) {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var p = currency.Pair{
|
||||
Delimiter: "",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.EUR,
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Base: currency.BTC,
|
||||
Quote: currency.EUR,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := l.SubmitOrder(p, exchange.BuyOrderSide, exchange.LimitOrderType, 1, 10, "hi")
|
||||
response, err := l.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -255,8 +255,16 @@ func (l *LocalBitcoins) GetExchangeHistory(p currency.Pair, assetType assets.Ass
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (l *LocalBitcoins) SubmitOrder(p currency.Pair, side exchange.OrderSide, _ exchange.OrderType, amount, _ float64, _ string) (exchange.SubmitOrderResponse, error) {
|
||||
func (l *LocalBitcoins) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
// These are placeholder details
|
||||
// TODO store a user's localbitcoin details to use here
|
||||
var params = AdCreate{
|
||||
@@ -266,17 +274,17 @@ func (l *LocalBitcoins) SubmitOrder(p currency.Pair, side exchange.OrderSide, _
|
||||
City: "City",
|
||||
Location: "Location",
|
||||
CountryCode: "US",
|
||||
Currency: p.Quote.String(),
|
||||
Currency: order.Pair.Quote.String(),
|
||||
AccountInfo: "-",
|
||||
BankName: "Bank",
|
||||
MSG: side.ToString(),
|
||||
MSG: order.OrderSide.ToString(),
|
||||
SMSVerficationRequired: true,
|
||||
TrackMaxAmount: true,
|
||||
RequireTrustedByAdvertiser: true,
|
||||
RequireIdentification: true,
|
||||
OnlineProvider: "",
|
||||
TradeType: "",
|
||||
MinAmount: int(math.Round(amount)),
|
||||
MinAmount: int(math.Round(order.Amount)),
|
||||
}
|
||||
|
||||
// Does not return any orderID, so create the add, then get the order
|
||||
|
||||
@@ -1045,13 +1045,18 @@ func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
// TestSubmitOrder Wrapper test
|
||||
func TestSubmitOrder(t *testing.T) {
|
||||
TestSetRealOrderDefaults(t)
|
||||
var p = currency.Pair{
|
||||
Delimiter: "",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.EUR,
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USD,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := o.SubmitOrder(p, exchange.BuyOrderSide,
|
||||
exchange.LimitOrderType, 1, 10, "hi")
|
||||
response, err := o.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -1815,13 +1815,18 @@ func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
func TestSubmitOrder(t *testing.T) {
|
||||
TestSetRealOrderDefaults(t)
|
||||
t.Parallel()
|
||||
var p = currency.Pair{
|
||||
Delimiter: "",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USDT,
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USDT,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := o.SubmitOrder(p, exchange.BuyOrderSide,
|
||||
exchange.LimitOrderType, 1, 10, "hi")
|
||||
response, err := o.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -206,25 +206,34 @@ func (o *OKGroup) GetExchangeHistory(p currency.Pair, assetType assets.AssetType
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (o *OKGroup) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, clientID string) (resp exchange.SubmitOrderResponse, err error) {
|
||||
request := PlaceSpotOrderRequest{
|
||||
ClientOID: clientID,
|
||||
InstrumentID: o.FormatExchangeCurrency(p, assets.AssetTypeSpot).String(),
|
||||
Side: strings.ToLower(side.ToString()),
|
||||
Type: strings.ToLower(orderType.ToString()),
|
||||
Size: strconv.FormatFloat(amount, 'f', -1, 64),
|
||||
func (o *OKGroup) SubmitOrder(order *exchange.OrderSubmission) (resp exchange.SubmitOrderResponse, err error) {
|
||||
if order == nil {
|
||||
return resp, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
if orderType == exchange.LimitOrderType {
|
||||
request.Price = strconv.FormatFloat(price, 'f', -1, 64)
|
||||
|
||||
err = order.Validate()
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
request := PlaceSpotOrderRequest{
|
||||
ClientOID: order.ClientID,
|
||||
InstrumentID: o.FormatExchangeCurrency(order.Pair, assets.AssetTypeSpot).String(),
|
||||
Side: strings.ToLower(order.OrderSide.ToString()),
|
||||
Type: strings.ToLower(order.OrderType.ToString()),
|
||||
Size: strconv.FormatFloat(order.Amount, 'f', -1, 64),
|
||||
}
|
||||
if order.OrderType == exchange.LimitOrderType {
|
||||
request.Price = strconv.FormatFloat(order.Price, 'f', -1, 64)
|
||||
}
|
||||
|
||||
orderResponse, err := o.PlaceSpotOrder(&request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
resp.IsOrderPlaced = orderResponse.Result
|
||||
resp.OrderID = orderResponse.OrderID
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
380
exchanges/order_types.go
Normal file
380
exchanges/order_types.go
Normal file
@@ -0,0 +1,380 @@
|
||||
package exchange
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/assets"
|
||||
)
|
||||
|
||||
// vars related to orders
|
||||
var (
|
||||
ErrOrderSubmissionIsNil = errors.New("order submission is nil")
|
||||
)
|
||||
|
||||
// OrderSubmission contains the order submission data
|
||||
type OrderSubmission struct {
|
||||
Pair currency.Pair
|
||||
OrderSide OrderSide
|
||||
OrderType OrderType
|
||||
Price float64
|
||||
Amount float64
|
||||
ClientID string
|
||||
}
|
||||
|
||||
// Validate checks the supplied data and returns whether or not its valid
|
||||
func (o *OrderSubmission) Validate() error {
|
||||
if o.Pair.IsEmpty() {
|
||||
return errors.New("order pair is empty")
|
||||
}
|
||||
|
||||
if o.OrderSide != BuyOrderSide && o.OrderSide != SellOrderSide ||
|
||||
o.OrderSide != BidOrderSide && o.OrderSide != AskOrderSide {
|
||||
return errors.New("order side is invalid")
|
||||
}
|
||||
|
||||
if o.OrderType != MarketOrderType && o.OrderType != LimitOrderType {
|
||||
return errors.New("order type is invalid")
|
||||
}
|
||||
|
||||
if o.Amount <= 0 {
|
||||
return errors.New("order amount is invalid")
|
||||
}
|
||||
|
||||
if o.OrderType == LimitOrderType && o.Price <= 0 {
|
||||
return errors.New("order price must be set if limit order type is desired")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SubmitOrderResponse is what is returned after submitting an order to an exchange
|
||||
type SubmitOrderResponse struct {
|
||||
IsOrderPlaced bool
|
||||
OrderID string
|
||||
}
|
||||
|
||||
// ModifyOrder is a an order modifyer
|
||||
type ModifyOrder struct {
|
||||
OrderID string
|
||||
OrderType
|
||||
OrderSide
|
||||
Price float64
|
||||
Amount float64
|
||||
LimitPriceUpper float64
|
||||
LimitPriceLower float64
|
||||
CurrencyPair currency.Pair
|
||||
ImmediateOrCancel bool
|
||||
HiddenOrder bool
|
||||
FillOrKill bool
|
||||
PostOnly bool
|
||||
}
|
||||
|
||||
// ModifyOrderResponse is an order modifying return type
|
||||
type ModifyOrderResponse struct {
|
||||
OrderID string
|
||||
}
|
||||
|
||||
// CancelAllOrdersResponse returns the status from attempting to cancel all orders on an exchagne
|
||||
type CancelAllOrdersResponse struct {
|
||||
OrderStatus map[string]string
|
||||
}
|
||||
|
||||
// OrderType enforces a standard for Ordertypes across the code base
|
||||
type OrderType string
|
||||
|
||||
// OrderType ...types
|
||||
const (
|
||||
AnyOrderType OrderType = "ANY"
|
||||
LimitOrderType OrderType = "LIMIT"
|
||||
MarketOrderType OrderType = "MARKET"
|
||||
ImmediateOrCancelOrderType OrderType = "IMMEDIATE_OR_CANCEL"
|
||||
StopOrderType OrderType = "STOP"
|
||||
TrailingStopOrderType OrderType = "TRAILINGSTOP"
|
||||
UnknownOrderType OrderType = "UNKNOWN"
|
||||
)
|
||||
|
||||
// ToLower changes the ordertype to lower case
|
||||
func (o OrderType) ToLower() OrderType {
|
||||
return OrderType(strings.ToLower(string(o)))
|
||||
}
|
||||
|
||||
// ToString changes the ordertype to the exchange standard and returns a string
|
||||
func (o OrderType) ToString() string {
|
||||
return fmt.Sprintf("%v", o)
|
||||
}
|
||||
|
||||
// OrderSide enforces a standard for OrderSides across the code base
|
||||
type OrderSide string
|
||||
|
||||
// OrderSide types
|
||||
const (
|
||||
AnyOrderSide OrderSide = "ANY"
|
||||
BuyOrderSide OrderSide = "BUY"
|
||||
SellOrderSide OrderSide = "SELL"
|
||||
BidOrderSide OrderSide = "BID"
|
||||
AskOrderSide OrderSide = "ASK"
|
||||
)
|
||||
|
||||
// ToLower changes the ordertype to lower case
|
||||
func (o OrderSide) ToLower() OrderSide {
|
||||
return OrderSide(strings.ToLower(string(o)))
|
||||
}
|
||||
|
||||
// ToString changes the ordertype to the exchange standard and returns a string
|
||||
func (o OrderSide) ToString() string {
|
||||
return fmt.Sprintf("%v", o)
|
||||
}
|
||||
|
||||
// OrderDetail holds order detail data
|
||||
type OrderDetail struct {
|
||||
Exchange string
|
||||
AccountID string
|
||||
ID string
|
||||
CurrencyPair currency.Pair
|
||||
OrderSide OrderSide
|
||||
OrderType OrderType
|
||||
OrderDate time.Time
|
||||
Status string
|
||||
Price float64
|
||||
Amount float64
|
||||
ExecutedAmount float64
|
||||
RemainingAmount float64
|
||||
Fee float64
|
||||
Trades []TradeHistory
|
||||
}
|
||||
|
||||
// OrderCancellation type required when requesting to cancel an order
|
||||
type OrderCancellation struct {
|
||||
AccountID string
|
||||
OrderID string
|
||||
CurrencyPair currency.Pair
|
||||
AssetType assets.AssetType
|
||||
WalletAddress string
|
||||
Side OrderSide
|
||||
}
|
||||
|
||||
// GetOrdersRequest used for GetOrderHistory and GetOpenOrders wrapper functions
|
||||
type GetOrdersRequest struct {
|
||||
OrderType OrderType
|
||||
OrderSide OrderSide
|
||||
StartTicks time.Time
|
||||
EndTicks time.Time
|
||||
// Currencies Empty array = all currencies. Some endpoints only support singular currency enquiries
|
||||
Currencies []currency.Pair
|
||||
}
|
||||
|
||||
// OrderStatus defines order status types
|
||||
type OrderStatus string
|
||||
|
||||
// All OrderStatus types
|
||||
const (
|
||||
AnyOrderStatus OrderStatus = "ANY"
|
||||
NewOrderStatus OrderStatus = "NEW"
|
||||
ActiveOrderStatus OrderStatus = "ACTIVE"
|
||||
PartiallyFilledOrderStatus OrderStatus = "PARTIALLY_FILLED"
|
||||
FilledOrderStatus OrderStatus = "FILLED"
|
||||
CancelledOrderStatus OrderStatus = "CANCELED"
|
||||
PendingCancelOrderStatus OrderStatus = "PENDING_CANCEL"
|
||||
RejectedOrderStatus OrderStatus = "REJECTED"
|
||||
ExpiredOrderStatus OrderStatus = "EXPIRED"
|
||||
HiddenOrderStatus OrderStatus = "HIDDEN"
|
||||
UnknownOrderStatus OrderStatus = "UNKNOWN"
|
||||
)
|
||||
|
||||
// FilterOrdersBySide removes any OrderDetails that don't match the orderStatus provided
|
||||
func FilterOrdersBySide(orders *[]OrderDetail, orderSide OrderSide) {
|
||||
if orderSide == "" || orderSide == AnyOrderSide {
|
||||
return
|
||||
}
|
||||
|
||||
var filteredOrders []OrderDetail
|
||||
for i := range *orders {
|
||||
if strings.EqualFold(string((*orders)[i].OrderSide), string(orderSide)) {
|
||||
filteredOrders = append(filteredOrders, (*orders)[i])
|
||||
}
|
||||
}
|
||||
|
||||
*orders = filteredOrders
|
||||
}
|
||||
|
||||
// FilterOrdersByType removes any OrderDetails that don't match the orderType provided
|
||||
func FilterOrdersByType(orders *[]OrderDetail, orderType OrderType) {
|
||||
if orderType == "" || orderType == AnyOrderType {
|
||||
return
|
||||
}
|
||||
|
||||
var filteredOrders []OrderDetail
|
||||
for i := range *orders {
|
||||
if strings.EqualFold(string((*orders)[i].OrderType), string(orderType)) {
|
||||
filteredOrders = append(filteredOrders, (*orders)[i])
|
||||
}
|
||||
}
|
||||
|
||||
*orders = filteredOrders
|
||||
}
|
||||
|
||||
// FilterOrdersByTickRange removes any OrderDetails outside of the tick range
|
||||
func FilterOrdersByTickRange(orders *[]OrderDetail, startTicks, endTicks time.Time) {
|
||||
if startTicks.IsZero() || endTicks.IsZero() ||
|
||||
startTicks.Unix() == 0 || endTicks.Unix() == 0 || endTicks.Before(startTicks) {
|
||||
return
|
||||
}
|
||||
|
||||
var filteredOrders []OrderDetail
|
||||
for i := range *orders {
|
||||
if (*orders)[i].OrderDate.Unix() >= startTicks.Unix() && (*orders)[i].OrderDate.Unix() <= endTicks.Unix() {
|
||||
filteredOrders = append(filteredOrders, (*orders)[i])
|
||||
}
|
||||
}
|
||||
|
||||
*orders = filteredOrders
|
||||
}
|
||||
|
||||
// FilterOrdersByCurrencies removes any OrderDetails that do not match the provided currency list
|
||||
// It is forgiving in that the provided currencies can match quote or base currencies
|
||||
func FilterOrdersByCurrencies(orders *[]OrderDetail, currencies []currency.Pair) {
|
||||
if len(currencies) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var filteredOrders []OrderDetail
|
||||
for i := range *orders {
|
||||
matchFound := false
|
||||
for _, c := range currencies {
|
||||
if !matchFound && (*orders)[i].CurrencyPair.EqualIncludeReciprocal(c) {
|
||||
matchFound = true
|
||||
}
|
||||
}
|
||||
|
||||
if matchFound {
|
||||
filteredOrders = append(filteredOrders, (*orders)[i])
|
||||
}
|
||||
}
|
||||
|
||||
*orders = filteredOrders
|
||||
}
|
||||
|
||||
// ByPrice used for sorting orders by price
|
||||
type ByPrice []OrderDetail
|
||||
|
||||
func (b ByPrice) Len() int {
|
||||
return len(b)
|
||||
}
|
||||
|
||||
func (b ByPrice) Less(i, j int) bool {
|
||||
return b[i].Price < b[j].Price
|
||||
}
|
||||
|
||||
func (b ByPrice) Swap(i, j int) {
|
||||
b[i], b[j] = b[j], b[i]
|
||||
}
|
||||
|
||||
// SortOrdersByPrice the caller function to sort orders
|
||||
func SortOrdersByPrice(orders *[]OrderDetail, reverse bool) {
|
||||
if reverse {
|
||||
sort.Sort(sort.Reverse(ByPrice(*orders)))
|
||||
} else {
|
||||
sort.Sort(ByPrice(*orders))
|
||||
}
|
||||
}
|
||||
|
||||
// ByOrderType used for sorting orders by order type
|
||||
type ByOrderType []OrderDetail
|
||||
|
||||
func (b ByOrderType) Len() int {
|
||||
return len(b)
|
||||
}
|
||||
|
||||
func (b ByOrderType) Less(i, j int) bool {
|
||||
return b[i].OrderType.ToString() < b[j].OrderType.ToString()
|
||||
}
|
||||
|
||||
func (b ByOrderType) Swap(i, j int) {
|
||||
b[i], b[j] = b[j], b[i]
|
||||
}
|
||||
|
||||
// SortOrdersByType the caller function to sort orders
|
||||
func SortOrdersByType(orders *[]OrderDetail, reverse bool) {
|
||||
if reverse {
|
||||
sort.Sort(sort.Reverse(ByOrderType(*orders)))
|
||||
} else {
|
||||
sort.Sort(ByOrderType(*orders))
|
||||
}
|
||||
}
|
||||
|
||||
// ByCurrency used for sorting orders by order currency
|
||||
type ByCurrency []OrderDetail
|
||||
|
||||
func (b ByCurrency) Len() int {
|
||||
return len(b)
|
||||
}
|
||||
|
||||
func (b ByCurrency) Less(i, j int) bool {
|
||||
return b[i].CurrencyPair.String() < b[j].CurrencyPair.String()
|
||||
}
|
||||
|
||||
func (b ByCurrency) Swap(i, j int) {
|
||||
b[i], b[j] = b[j], b[i]
|
||||
}
|
||||
|
||||
// SortOrdersByCurrency the caller function to sort orders
|
||||
func SortOrdersByCurrency(orders *[]OrderDetail, reverse bool) {
|
||||
if reverse {
|
||||
sort.Sort(sort.Reverse(ByCurrency(*orders)))
|
||||
} else {
|
||||
sort.Sort(ByCurrency(*orders))
|
||||
}
|
||||
}
|
||||
|
||||
// ByDate used for sorting orders by order date
|
||||
type ByDate []OrderDetail
|
||||
|
||||
func (b ByDate) Len() int {
|
||||
return len(b)
|
||||
}
|
||||
|
||||
func (b ByDate) Less(i, j int) bool {
|
||||
return b[i].OrderDate.Unix() < b[j].OrderDate.Unix()
|
||||
}
|
||||
|
||||
func (b ByDate) Swap(i, j int) {
|
||||
b[i], b[j] = b[j], b[i]
|
||||
}
|
||||
|
||||
// SortOrdersByDate the caller function to sort orders
|
||||
func SortOrdersByDate(orders *[]OrderDetail, reverse bool) {
|
||||
if reverse {
|
||||
sort.Sort(sort.Reverse(ByDate(*orders)))
|
||||
} else {
|
||||
sort.Sort(ByDate(*orders))
|
||||
}
|
||||
}
|
||||
|
||||
// ByOrderSide used for sorting orders by order side (buy sell)
|
||||
type ByOrderSide []OrderDetail
|
||||
|
||||
func (b ByOrderSide) Len() int {
|
||||
return len(b)
|
||||
}
|
||||
|
||||
func (b ByOrderSide) Less(i, j int) bool {
|
||||
return b[i].OrderSide.ToString() < b[j].OrderSide.ToString()
|
||||
}
|
||||
|
||||
func (b ByOrderSide) Swap(i, j int) {
|
||||
b[i], b[j] = b[j], b[i]
|
||||
}
|
||||
|
||||
// SortOrdersBySide the caller function to sort orders
|
||||
func SortOrdersBySide(orders *[]OrderDetail, reverse bool) {
|
||||
if reverse {
|
||||
sort.Sort(sort.Reverse(ByOrderSide(*orders)))
|
||||
} else {
|
||||
sort.Sort(ByOrderSide(*orders))
|
||||
}
|
||||
}
|
||||
@@ -253,19 +253,19 @@ func TestSubmitOrder(t *testing.T) {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var pair = currency.Pair{
|
||||
Delimiter: "_",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.LTC,
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Delimiter: "_",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.LTC,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
|
||||
response, err := p.SubmitOrder(pair,
|
||||
exchange.BuyOrderSide,
|
||||
exchange.LimitOrderType,
|
||||
1,
|
||||
10,
|
||||
"hi")
|
||||
|
||||
response, err := p.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -302,26 +302,30 @@ func (p *Poloniex) GetExchangeHistory(currencyPair currency.Pair, assetType asse
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (p *Poloniex) SubmitOrder(currencyPair currency.Pair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, _ string) (exchange.SubmitOrderResponse, error) {
|
||||
func (p *Poloniex) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
fillOrKill := orderType == exchange.MarketOrderType
|
||||
isBuyOrder := side == exchange.BuyOrderSide
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
response, err := p.PlaceOrder(currencyPair.String(),
|
||||
price,
|
||||
amount,
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
fillOrKill := order.OrderType == exchange.MarketOrderType
|
||||
isBuyOrder := order.OrderSide == exchange.BuyOrderSide
|
||||
response, err := p.PlaceOrder(order.Pair.String(),
|
||||
order.Price,
|
||||
order.Amount,
|
||||
false,
|
||||
fillOrKill,
|
||||
isBuyOrder)
|
||||
|
||||
if response.OrderNumber > 0 {
|
||||
submitOrderResponse.OrderID = fmt.Sprintf("%v", response.OrderNumber)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
}
|
||||
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
|
||||
@@ -372,12 +372,19 @@ func TestSubmitOrder(t *testing.T) {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var pair = currency.Pair{
|
||||
Delimiter: "_",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USD,
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Delimiter: "_",
|
||||
Base: currency.BTC,
|
||||
Quote: currency.USD,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := y.SubmitOrder(pair, exchange.BuyOrderSide, exchange.LimitOrderType, 1, 10, "hi")
|
||||
response, err := y.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -281,22 +281,28 @@ func (y *Yobit) GetExchangeHistory(p currency.Pair, assetType assets.AssetType)
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
// Yobit only supports limit orders
|
||||
func (y *Yobit) SubmitOrder(p currency.Pair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, _ string) (exchange.SubmitOrderResponse, error) {
|
||||
func (y *Yobit) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
if orderType != exchange.LimitOrderType {
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
if order.OrderType != exchange.LimitOrderType {
|
||||
return submitOrderResponse, errors.New("only limit orders are allowed")
|
||||
}
|
||||
|
||||
response, err := y.Trade(p.String(), side.ToString(), amount, price)
|
||||
response, err := y.Trade(order.Pair.String(), order.OrderSide.ToString(),
|
||||
order.Amount, order.Price)
|
||||
if response > 0 {
|
||||
submitOrderResponse.OrderID = fmt.Sprintf("%v", response)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
}
|
||||
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
|
||||
@@ -288,25 +288,25 @@ func areTestAPIKeysSet() bool {
|
||||
func TestSubmitOrder(t *testing.T) {
|
||||
z.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip(fmt.Sprintf("ApiKey: %s. Can place orders: %v",
|
||||
z.API.Credentials.Key,
|
||||
canManipulateRealOrders))
|
||||
}
|
||||
var pair = currency.Pair{
|
||||
Delimiter: "_",
|
||||
Base: currency.QTUM,
|
||||
Quote: currency.USDT,
|
||||
|
||||
var orderSubmission = &exchange.OrderSubmission{
|
||||
Pair: currency.Pair{
|
||||
Delimiter: "_",
|
||||
Base: currency.QTUM,
|
||||
Quote: currency.USD,
|
||||
},
|
||||
OrderSide: exchange.BuyOrderSide,
|
||||
OrderType: exchange.LimitOrderType,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
|
||||
response, err := z.SubmitOrder(pair,
|
||||
exchange.BuyOrderSide,
|
||||
exchange.LimitOrderType,
|
||||
1,
|
||||
10,
|
||||
"hi")
|
||||
|
||||
response, err := z.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
@@ -300,32 +300,36 @@ func (z *ZB) GetExchangeHistory(p currency.Pair, assetType assets.AssetType) ([]
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (z *ZB) SubmitOrder(p currency.Pair, side exchange.OrderSide, _ exchange.OrderType, amount, price float64, _ string) (exchange.SubmitOrderResponse, error) {
|
||||
func (z *ZB) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
var oT SpotNewOrderRequestParamsType
|
||||
if order == nil {
|
||||
return submitOrderResponse, exchange.ErrOrderSubmissionIsNil
|
||||
}
|
||||
|
||||
if side == exchange.BuyOrderSide {
|
||||
if err := order.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
var oT SpotNewOrderRequestParamsType
|
||||
if order.OrderSide == exchange.BuyOrderSide {
|
||||
oT = SpotNewOrderRequestParamsTypeBuy
|
||||
} else {
|
||||
oT = SpotNewOrderRequestParamsTypeSell
|
||||
}
|
||||
|
||||
var params = SpotNewOrderRequestParams{
|
||||
Amount: amount,
|
||||
Price: price,
|
||||
Symbol: strings.ToLower(p.String()),
|
||||
Amount: order.Amount,
|
||||
Price: order.Price,
|
||||
Symbol: order.Pair.Lower().String(),
|
||||
Type: oT,
|
||||
}
|
||||
response, err := z.SpotNewOrder(params)
|
||||
|
||||
if response > 0 {
|
||||
submitOrderResponse.OrderID = fmt.Sprintf("%v", response)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
}
|
||||
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user