Skip to content

Commit

Permalink
[Feature] Add ability to place stop order (#61)
Browse files Browse the repository at this point in the history
  • Loading branch information
dougdellolio authored Feb 4, 2018
1 parent 1dac933 commit c656f27
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 11 deletions.
52 changes: 50 additions & 2 deletions GDAXClient.Specs/JsonFixtures/Orders/OrderResponseFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,31 @@
{
public static class OrderResponseFixture
{
public static string Create()
public static string CreateMarketOrder()
{
var json = @"
{
""id"": ""d0c5340b-6d6c-49d9-b567-48c4bfca13d2"",
""price"": ""0.10000000"",
""size"": ""0.01000000"",
""product_id"": ""BTC-USD"",
""side"": ""buy"",
""stp"": ""dc"",
""type"": ""market"",
""time_in_force"": ""GTC"",
""post_only"": false,
""created_at"": ""2016-12-08T24:00:00Z"",
""fill_fees"": ""0.0000000000000000"",
""filled_size"": ""0.00000000"",
""executed_value"": ""0.0000000000000000"",
""status"": ""pending"",
""settled"": false
}";

return json;
}

public static string CreateLimitOrder()
{
var json = @"
{
Expand All @@ -26,7 +50,31 @@ public static string Create()
return json;
}

public static string CreateMany()
public static string CreateStopOrder()
{
var json = @"
{
""id"": ""d0c5340b-6d6c-49d9-b567-48c4bfca13d2"",
""price"": ""0.10000000"",
""size"": ""0.01000000"",
""product_id"": ""BTC-USD"",
""side"": ""buy"",
""stp"": ""dc"",
""type"": ""stop"",
""time_in_force"": ""GTC"",
""post_only"": false,
""created_at"": ""2016-12-08T24:00:00Z"",
""fill_fees"": ""0.0000000000000000"",
""filled_size"": ""0.00000000"",
""executed_value"": ""0.0000000000000000"",
""status"": ""pending"",
""settled"": false
}";

return json;
}

public static string CreateLimitOrderMany()
{
var json = @"
[
Expand Down
51 changes: 44 additions & 7 deletions GDAXClient.Specs/Services/Orders/OrdersServiceSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,21 @@ class when_placing_a_market_order
.Return(Task.FromResult(new HttpResponseMessage()));

The<IHttpClient>().WhenToldTo(p => p.ReadAsStringAsync(Param.IsAny<HttpResponseMessage>()))
.Return(Task.FromResult(OrderResponseFixture.Create()));
.Return(Task.FromResult(OrderResponseFixture.CreateMarketOrder()));
};

Because of = () =>
order_response_result = Subject.PlaceMarketOrderAsync(OrderSide.Buy, ProductType.BtcUsd, .01M).Result;

It should_have_correct_account_information = () =>
It should_have_correct_order_information = () =>
{
order_response_result.Id.ShouldEqual(new Guid("d0c5340b-6d6c-49d9-b567-48c4bfca13d2"));
order_response_result.Price.ShouldEqual(0.10000000M);
order_response_result.Size.ShouldEqual(0.01000000M);
order_response_result.Product_id.ShouldEqual("BTC-USD");
order_response_result.Side.ShouldEqual("buy");
order_response_result.Stp.ShouldEqual("dc");
order_response_result.Type.ShouldEqual("limit");
order_response_result.Type.ShouldEqual("market");
order_response_result.Time_in_force.ShouldEqual("GTC");
order_response_result.Post_only.ShouldBeFalse();
order_response_result.Created_at.ShouldEqual(new DateTime(2016, 12, 9));
Expand All @@ -81,13 +81,13 @@ class when_placing_a_limit_order
.Return(Task.FromResult(new HttpResponseMessage()));

The<IHttpClient>().WhenToldTo(p => p.ReadAsStringAsync(Param.IsAny<HttpResponseMessage>()))
.Return(Task.FromResult(OrderResponseFixture.Create()));
.Return(Task.FromResult(OrderResponseFixture.CreateLimitOrder()));
};

Because of = () =>
order_response_result = Subject.PlaceLimitOrderAsync(OrderSide.Buy, ProductType.BtcUsd, .01M, 0.1M, GoodTillTime.Min).Result;

It should_have_correct_account_information = () =>
It should_have_correct_order_information = () =>
{
order_response_result.Id.ShouldEqual(new Guid("d0c5340b-6d6c-49d9-b567-48c4bfca13d2"));
order_response_result.Price.ShouldEqual(0.10000000M);
Expand All @@ -107,6 +107,43 @@ class when_placing_a_limit_order
};
}

class when_placing_a_stop_order
{
Establish context = () =>
{
The<IHttpRequestMessageService>().WhenToldTo(p => p.CreateHttpRequestMessage(Param.IsAny<HttpMethod>(), Param.IsAny<Authenticator>(), Param.IsAny<string>(), Param.IsAny<string>()))
.Return(new HttpRequestMessage());

The<IHttpClient>().WhenToldTo(p => p.SendASync(Param.IsAny<HttpRequestMessage>()))
.Return(Task.FromResult(new HttpResponseMessage()));

The<IHttpClient>().WhenToldTo(p => p.ReadAsStringAsync(Param.IsAny<HttpResponseMessage>()))
.Return(Task.FromResult(OrderResponseFixture.CreateStopOrder()));
};

Because of = () =>
order_response_result = Subject.PlaceStopOrderAsync(OrderSide.Buy, ProductType.BtcUsd, .01M, .1M).Result;

It should_have_correct_order_information = () =>
{
order_response_result.Id.ShouldEqual(new Guid("d0c5340b-6d6c-49d9-b567-48c4bfca13d2"));
order_response_result.Price.ShouldEqual(0.10000000M);
order_response_result.Size.ShouldEqual(0.01000000M);
order_response_result.Product_id.ShouldEqual("BTC-USD");
order_response_result.Side.ShouldEqual("buy");
order_response_result.Stp.ShouldEqual("dc");
order_response_result.Type.ShouldEqual("stop");
order_response_result.Time_in_force.ShouldEqual("GTC");
order_response_result.Post_only.ShouldBeFalse();
order_response_result.Created_at.ShouldEqual(new DateTime(2016, 12, 9));
order_response_result.Fill_fees.ShouldEqual(0.0000000000000000M);
order_response_result.Filled_size.ShouldEqual(0.00000000M);
order_response_result.Executed_value.ShouldEqual(0.0000000000000000M);
order_response_result.Status.ShouldEqual("pending");
order_response_result.Settled.ShouldBeFalse();
};
}

class when_cancelling_all_orders
{
Establish context = () =>
Expand Down Expand Up @@ -193,7 +230,7 @@ class when_getting_all_orders
.Return(Task.FromResult(new HttpResponseMessage()));

The<IHttpClient>().WhenToldTo(p => p.ReadAsStringAsync(Param.IsAny<HttpResponseMessage>()))
.Return(Task.FromResult(OrderResponseFixture.CreateMany()));
.Return(Task.FromResult(OrderResponseFixture.CreateLimitOrderMany()));
};

Because of = () =>
Expand Down Expand Up @@ -249,7 +286,7 @@ class when_getting_order_by_id
.Return(Task.FromResult(new HttpResponseMessage()));

The<IHttpClient>().WhenToldTo(p => p.ReadAsStringAsync(Param.IsAny<HttpResponseMessage>()))
.Return(Task.FromResult(OrderResponseFixture.Create()));
.Return(Task.FromResult(OrderResponseFixture.CreateLimitOrder()));
};

Because of = () =>
Expand Down
2 changes: 2 additions & 0 deletions GDAXClient/Services/Orders/Models/Order.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,7 @@ public class Order
public string time_in_force { get; set; }

public string cancel_after { get; set; }

public bool post_only { get; set; }
}
}
28 changes: 26 additions & 2 deletions GDAXClient/Services/Orders/OrdersService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ public async Task<OrderResponse> PlaceLimitOrderAsync(
type = OrderType.Limit.ToString().ToLower(),
price = price,
size = size,
time_in_force = timeInForce.ToString().ToUpper()
time_in_force = timeInForce.ToString().ToUpper(),
post_only = postOnly
});

var httpResponseMessage = await SendHttpRequestMessageAsync(HttpMethod.Post, authenticator, "/orders", newOrder).ConfigureAwait(false);
Expand All @@ -91,7 +92,30 @@ public async Task<OrderResponse> PlaceLimitOrderAsync(
type = OrderType.Limit.ToString().ToLower(),
price = price,
size = size,
cancel_after = cancelAfter.ToString().ToLower()
cancel_after = cancelAfter.ToString().ToLower(),
post_only = postOnly
});

var httpResponseMessage = await SendHttpRequestMessageAsync(HttpMethod.Post, authenticator, "/orders", newOrder);
var contentBody = await httpClient.ReadAsStringAsync(httpResponseMessage).ConfigureAwait(false);
var orderResponse = JsonConvert.DeserializeObject<OrderResponse>(contentBody);

return orderResponse;
}

public async Task<OrderResponse> PlaceStopOrderAsync(
OrderSide side,
ProductType productPair,
decimal size,
decimal stopPrice)
{
var newOrder = JsonConvert.SerializeObject(new Order
{
side = side.ToString().ToLower(),
product_id = productPair.ToDasherizedUpper(),
type = OrderType.Stop.ToString().ToLower(),
price = stopPrice,
size = size
});

var httpResponseMessage = await SendHttpRequestMessageAsync(HttpMethod.Post, authenticator, "/orders", newOrder);
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ var allAccounts = await gdaxClient.AccountsService.GetAllAccountsAsync();
- PlaceMarketOrderAsync(orderSide, productPair, size) - place market order
- PlaceLimitOrderAsync(orderSide, productPair, size, price, timeInForce, postOnly) - place limit order with time in force
- PlaceLimitOrderAsync(orderSide, productPair, size, price, cancelAfter, postOnly) - place limit order with cancel after date
- PlaceStopOrderAsync(orderSide, productPair, size, stopPrice) - place stop order with stop price
- CancelAllOrdersAsync() - cancel all orders
- CancelOrderByIdAsync(id) - cancel order by id
- GetAllOrdersAsync(limit) - get all open or un-settled orders (paged response)
Expand Down

0 comments on commit c656f27

Please sign in to comment.