Engine improvements

This commit is contained in:
Adrian Gallagher
2019-06-10 20:02:09 +10:00
parent 04c7c4895f
commit f777e68716
88 changed files with 2037 additions and 1413 deletions

View File

@@ -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")
}

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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,
"",

View File

@@ -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 {

View File

@@ -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,
}

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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 != "" {

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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:

View File

@@ -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 {

View File

@@ -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) {

View File

@@ -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

View File

@@ -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 {

View File

@@ -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)
}

View File

@@ -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 {

View File

@@ -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)
}

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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
View 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))
}
}

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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
}