Skip to content

Commit

Permalink
Merge pull request #15 from fremantle-capital/fill-or-kill-and-immedi…
Browse files Browse the repository at this point in the history
…ate-or-cancel-orders

Add support for FOK & IOC limit orders
  • Loading branch information
dvcrn authored Jun 28, 2018
2 parents 8d1be91 + d2d7332 commit 189f785
Show file tree
Hide file tree
Showing 6 changed files with 262 additions and 8 deletions.
41 changes: 41 additions & 0 deletions fixture/vcr_cassettes/order_limit_buy_fill_or_kill_success.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
[
{
"request": {
"body": "price=0.01&quantity=0.1&recvWindow=1000&side=BUY&symbol=LTCBTC&timeInForce=FOK&timestamp=1527290557371&type=LIMIT&signature=***",
"headers": {
"X-MBX-APIKEY": "***"
},
"method": "post",
"options": [],
"request_body": "",
"url": "https://api.binance.com/api/v3/order"
},
"response": {
"binary": false,
"body": "{\"symbol\":\"LTCBTC\",\"orderId\":47527179,\"clientOrderId\":\"dY67P33S4IxPnJGx5EtuSf\",\"transactTime\":1527290557607,\"price\":\"0.01000000\",\"origQty\":\"0.10000000\",\"executedQty\":\"0.00000000\",\"status\":\"EXPIRED\",\"timeInForce\":\"FOK\",\"type\":\"LIMIT\",\"side\":\"BUY\"}",
"headers": {
"Content-Type": "application/json",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive",
"Date": "Fri, 25 May 2018 23:22:37 GMT",
"Server": "nginx",
"Vary": "Accept-Encoding",
"Strict-Transport-Security": "max-age=31536000; includeSubdomains",
"X-Frame-Options": "SAMEORIGIN",
"X-Xss-Protection": "1; mode=block",
"X-Content-Type-Options": "nosniff",
"Content-Security-Policy": "default-src 'self'",
"X-Content-Security-Policy": "default-src 'self'",
"X-WebKit-CSP": "default-src 'self'",
"Cache-Control": "no-cache, no-store, must-revalidate",
"Pragma": "no-cache",
"Expires": "0",
"X-Cache": "Miss from cloudfront",
"Via": "1.1 aa42484f82c16d99015c599631def20c.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id": "EUJfEb7dmPCXVDExHIg_zyXCioBbrAvTnUO7W7oM0iXLb5u9RLfC4Q=="
},
"status_code": 200,
"type": "ok"
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
[
{
"request": {
"body": "price=0.01&quantity=0.1&recvWindow=1000&side=BUY&symbol=LTCBTC&timeInForce=IOC&timestamp=1527291300666&type=LIMIT&signature=***",
"headers": {
"X-MBX-APIKEY": "***"
},
"method": "post",
"options": [],
"request_body": "",
"url": "https://api.binance.com/api/v3/order"
},
"response": {
"binary": false,
"body": "{\"symbol\":\"LTCBTC\",\"orderId\":47528830,\"clientOrderId\":\"zyMyhtRENlvFHrl4CitDe0\",\"transactTime\":1527291300912,\"price\":\"0.01000000\",\"origQty\":\"0.10000000\",\"executedQty\":\"0.00000000\",\"status\":\"EXPIRED\",\"timeInForce\":\"IOC\",\"type\":\"LIMIT\",\"side\":\"BUY\"}",
"headers": {
"Content-Type": "application/json",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive",
"Date": "Fri, 25 May 2018 23:35:00 GMT",
"Server": "nginx",
"Vary": "Accept-Encoding",
"Strict-Transport-Security": "max-age=31536000; includeSubdomains",
"X-Frame-Options": "SAMEORIGIN",
"X-Xss-Protection": "1; mode=block",
"X-Content-Type-Options": "nosniff",
"Content-Security-Policy": "default-src 'self'",
"X-Content-Security-Policy": "default-src 'self'",
"X-WebKit-CSP": "default-src 'self'",
"Cache-Control": "no-cache, no-store, must-revalidate",
"Pragma": "no-cache",
"Expires": "0",
"X-Cache": "Miss from cloudfront",
"Via": "1.1 fb1574d5a6ba2d77d2a656aba08aa3c3.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id": "7FpRejCpXjYssWLkFBBSqvrIlcQQUmXaFGh4q1eFUpiWvRc91Ipo2g=="
},
"status_code": 200,
"type": "ok"
}
}
]
41 changes: 41 additions & 0 deletions fixture/vcr_cassettes/order_limit_sell_fill_or_kill_success.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
[
{
"request": {
"body": "price=50000&quantity=0.001&recvWindow=1000&side=SELL&symbol=BTCUSDT&timeInForce=FOK&timestamp=1527290985049&type=LIMIT&signature=***",
"headers": {
"X-MBX-APIKEY": "***"
},
"method": "post",
"options": [],
"request_body": "",
"url": "https://api.binance.com/api/v3/order"
},
"response": {
"binary": false,
"body": "{\"symbol\":\"BTCUSDT\",\"orderId\":108277184,\"clientOrderId\":\"lKYECwEPSTPzurwx6emuN2\",\"transactTime\":1527290985305,\"price\":\"50000.00000000\",\"origQty\":\"0.00100000\",\"executedQty\":\"0.00000000\",\"status\":\"EXPIRED\",\"timeInForce\":\"FOK\",\"type\":\"LIMIT\",\"side\":\"SELL\"}",
"headers": {
"Content-Type": "application/json",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive",
"Date": "Fri, 25 May 2018 23:29:45 GMT",
"Server": "nginx",
"Vary": "Accept-Encoding",
"Strict-Transport-Security": "max-age=31536000; includeSubdomains",
"X-Frame-Options": "SAMEORIGIN",
"X-Xss-Protection": "1; mode=block",
"X-Content-Type-Options": "nosniff",
"Content-Security-Policy": "default-src 'self'",
"X-Content-Security-Policy": "default-src 'self'",
"X-WebKit-CSP": "default-src 'self'",
"Cache-Control": "no-cache, no-store, must-revalidate",
"Pragma": "no-cache",
"Expires": "0",
"X-Cache": "Miss from cloudfront",
"Via": "1.1 68807936c056006818525c5da31d108e.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id": "w3qEO4sfOGkq_SUsElVerpJPvffAYa-rxZGUfgpZhsoAXlQBqzJwTg=="
},
"status_code": 200,
"type": "ok"
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
[
{
"request": {
"body": "price=50000&quantity=0.001&recvWindow=1000&side=SELL&symbol=BTCUSDT&timeInForce=IOC&timestamp=1527291410866&type=LIMIT&signature=***",
"headers": {
"X-MBX-APIKEY": "***"
},
"method": "post",
"options": [],
"request_body": "",
"url": "https://api.binance.com/api/v3/order"
},
"response": {
"binary": false,
"body": "{\"symbol\":\"BTCUSDT\",\"orderId\":108279070,\"clientOrderId\":\"roSkLhwX9KCgYqr4yFPx1V\",\"transactTime\":1527291411088,\"price\":\"50000.00000000\",\"origQty\":\"0.00100000\",\"executedQty\":\"0.00000000\",\"status\":\"EXPIRED\",\"timeInForce\":\"IOC\",\"type\":\"LIMIT\",\"side\":\"SELL\"}",
"headers": {
"Content-Type": "application/json",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive",
"Date": "Fri, 25 May 2018 23:36:51 GMT",
"Server": "nginx",
"Vary": "Accept-Encoding",
"Strict-Transport-Security": "max-age=31536000; includeSubdomains",
"X-Frame-Options": "SAMEORIGIN",
"X-Xss-Protection": "1; mode=block",
"X-Content-Type-Options": "nosniff",
"Content-Security-Policy": "default-src 'self'",
"X-Content-Security-Policy": "default-src 'self'",
"X-WebKit-CSP": "default-src 'self'",
"Cache-Control": "no-cache, no-store, must-revalidate",
"Pragma": "no-cache",
"Expires": "0",
"X-Cache": "Miss from cloudfront",
"Via": "1.1 51f2e50a0d2a5ee1d9c830bf417b2713.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id": "BX8-X-VXYRrjfwPJ8H-Gx4sgVhcoBDZ7WlOiWn-u0SWuW2h0e5Rhpw=="
},
"status_code": 200,
"type": "ok"
}
}
]
30 changes: 22 additions & 8 deletions lib/binance.ex
Original file line number Diff line number Diff line change
Expand Up @@ -311,22 +311,29 @@ defmodule Binance do
Returns `{:ok, %{}}` or `{:error, reason}`
"""
def order_limit_buy(%Binance.TradePair{from: from, to: to} = symbol, quantity, price)
def order_limit_buy(symbol, quantity, price, time_in_force \\ "GTC")

def order_limit_buy(
%Binance.TradePair{from: from, to: to} = symbol,
quantity,
price,
time_in_force
)
when is_number(quantity)
when is_number(price)
when is_binary(from)
when is_binary(to) do
case find_symbol(symbol) do
{:ok, binance_symbol} -> order_limit_buy(binance_symbol, quantity, price)
{:ok, binance_symbol} -> order_limit_buy(binance_symbol, quantity, price, time_in_force)
e -> e
end
end

def order_limit_buy(symbol, quantity, price)
def order_limit_buy(symbol, quantity, price, time_in_force)
when is_binary(symbol)
when is_number(quantity)
when is_number(price) do
create_order(symbol, "BUY", "LIMIT", quantity, price, "GTC")
create_order(symbol, "BUY", "LIMIT", quantity, price, time_in_force)
|> parse_order_response
end

Expand All @@ -337,22 +344,29 @@ defmodule Binance do
Returns `{:ok, %{}}` or `{:error, reason}`
"""
def order_limit_sell(%Binance.TradePair{from: from, to: to} = symbol, quantity, price)
def order_limit_sell(symbol, quantity, price, time_in_force \\ "GTC")

def order_limit_sell(
%Binance.TradePair{from: from, to: to} = symbol,
quantity,
price,
time_in_force
)
when is_number(quantity)
when is_number(price)
when is_binary(from)
when is_binary(to) do
case find_symbol(symbol) do
{:ok, binance_symbol} -> order_limit_sell(binance_symbol, quantity, price)
{:ok, binance_symbol} -> order_limit_sell(binance_symbol, quantity, price, time_in_force)
e -> e
end
end

def order_limit_sell(symbol, quantity, price)
def order_limit_sell(symbol, quantity, price, time_in_force)
when is_binary(symbol)
when is_number(quantity)
when is_number(price) do
create_order(symbol, "SELL", "LIMIT", quantity, price, "GTC")
create_order(symbol, "SELL", "LIMIT", quantity, price, time_in_force)
|> parse_order_response
end

Expand Down
76 changes: 76 additions & 0 deletions test/binance_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,44 @@ defmodule BinanceTest do
assert response.type == "LIMIT"
end
end

test "can create an order with a fill or kill duration" do
use_cassette "order_limit_buy_fill_or_kill_success" do
assert {:ok, %Binance.OrderResponse{} = response} =
Binance.order_limit_buy("LTCBTC", 0.1, 0.01, "FOK")

assert response.client_order_id == "dY67P33S4IxPnJGx5EtuSf"
assert response.executed_qty == "0.00000000"
assert response.order_id == 47_527_179
assert response.orig_qty == "0.10000000"
assert response.price == "0.01000000"
assert response.side == "BUY"
assert response.status == "EXPIRED"
assert response.symbol == "LTCBTC"
assert response.time_in_force == "FOK"
assert response.transact_time == 1_527_290_557_607
assert response.type == "LIMIT"
end
end

test "can create an order with am immediate or cancel duration" do
use_cassette "order_limit_buy_immediate_or_cancel_success" do
assert {:ok, %Binance.OrderResponse{} = response} =
Binance.order_limit_buy("LTCBTC", 0.1, 0.01, "IOC")

assert response.client_order_id == "zyMyhtRENlvFHrl4CitDe0"
assert response.executed_qty == "0.00000000"
assert response.order_id == 47_528_830
assert response.orig_qty == "0.10000000"
assert response.price == "0.01000000"
assert response.side == "BUY"
assert response.status == "EXPIRED"
assert response.symbol == "LTCBTC"
assert response.time_in_force == "IOC"
assert response.transact_time == 1_527_291_300_912
assert response.type == "LIMIT"
end
end
end

describe ".order_limit_sell" do
Expand All @@ -128,5 +166,43 @@ defmodule BinanceTest do
assert response.type == "LIMIT"
end
end

test "can create an order with a fill or kill duration" do
use_cassette "order_limit_sell_fill_or_kill_success" do
assert {:ok, %Binance.OrderResponse{} = response} =
Binance.order_limit_sell("BTCUSDT", 0.001, 50_000, "FOK")

assert response.client_order_id == "lKYECwEPSTPzurwx6emuN2"
assert response.executed_qty == "0.00000000"
assert response.order_id == 108_277_184
assert response.orig_qty == "0.00100000"
assert response.price == "50000.00000000"
assert response.side == "SELL"
assert response.status == "EXPIRED"
assert response.symbol == "BTCUSDT"
assert response.time_in_force == "FOK"
assert response.transact_time == 1_527_290_985_305
assert response.type == "LIMIT"
end
end

test "can create an order with am immediate or cancel duration" do
use_cassette "order_limit_sell_immediate_or_cancel_success" do
assert {:ok, %Binance.OrderResponse{} = response} =
Binance.order_limit_sell("BTCUSDT", 0.001, 50_000, "IOC")

assert response.client_order_id == "roSkLhwX9KCgYqr4yFPx1V"
assert response.executed_qty == "0.00000000"
assert response.order_id == 108_279_070
assert response.orig_qty == "0.00100000"
assert response.price == "50000.00000000"
assert response.side == "SELL"
assert response.status == "EXPIRED"
assert response.symbol == "BTCUSDT"
assert response.time_in_force == "IOC"
assert response.transact_time == 1_527_291_411_088
assert response.type == "LIMIT"
end
end
end
end

0 comments on commit 189f785

Please sign in to comment.