Skip to content

Commit fe57b9b

Browse files
committed
Standardize isPostOnly
- a.k.a. MakerOnly or BookOrCancel or PendingOrCancelled - most exchanges support this, but vary in the parameters needed to specify this
1 parent a194c09 commit fe57b9b

27 files changed

+60
-27
lines changed

src/ExchangeSharp/API/Exchanges/Aquanow/ExchangeAquanowAPI.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ protected override async Task ProcessRequestAsync(IHttpWebRequest request, Dicti
105105
// DONE
106106
protected override async Task<ExchangeOrderResult> OnPlaceOrderAsync(ExchangeOrderRequest order)
107107
{
108+
if (order.IsPostOnly != null) throw new NotImplementedException("Post Only orders are not supported by this exchange or not implemented in ExchangeSharp. Please submit a PR if you are interested in this feature.");
108109
// In Aquanow market order, when buying crypto the amount of crypto that is bought is the receiveQuantity
109110
// and when selling the amount of crypto that is sold is the deliverQuantity
110111
string amountParameter = order.IsBuy ? "receiveQuantity" : "deliverQuantity";

src/ExchangeSharp/API/Exchanges/BL3P/ExchangeBL3PAPI.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ private string GetSignKey(IHttpWebRequest request, string formData)
233233

234234
protected override async Task<ExchangeOrderResult> OnPlaceOrderAsync(ExchangeOrderRequest order)
235235
{
236+
if (order.IsPostOnly != null) throw new NotImplementedException("Post Only orders are not supported by this exchange or not implemented in ExchangeSharp. Please submit a PR if you are interested in this feature.");
236237
var roundedAmount = order.RoundAmount();
237238
var amountInt = converterToEight.FromDecimal(roundedAmount);
238239

src/ExchangeSharp/API/Exchanges/BTSE/ExchangeBTSEAPI.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ protected override async Task<ExchangeOrderResult> OnPlaceOrderAsync(ExchangeOrd
165165
dict.Add("size", request.Amount);
166166
dict.Add("side", request.IsBuy ? "BUY" : "SELL");
167167
dict.Add("symbol", request.MarketSymbol);
168+
if (request.IsPostOnly != null) payload["postOnly"] = request.IsPostOnly;
168169

169170
switch (request.OrderType )
170171
{

src/ExchangeSharp/API/Exchanges/BinanceGroup/BinanceGroupCommon.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,11 @@ protected override async Task<ExchangeOrderResult> OnPlaceOrderAsync(ExchangeOrd
554554
payload["side"] = order.IsBuy ? "BUY" : "SELL";
555555
if (order.OrderType == OrderType.Stop)
556556
payload["type"] = "STOP_LOSS";//if order type is stop loss/limit, then binance expect word 'STOP_LOSS' inestead of 'STOP'
557+
else if (order.IsPostOnly == true)
558+
{
559+
if (order.OrderType == OrderType.Limit) payload["type"] = "LIMIT_MAKER"; // LIMIT_MAKER are LIMIT orders that will be rejected if they would immediately match and trade as a taker.
560+
else throw new NotImplementedException("PostOnly with non limit orders are not currently supported on Binance. Please submit a PR if you are interested in this feature");
561+
}
557562
else
558563
payload["type"] = order.OrderType.ToStringUpperInvariant();
559564

src/ExchangeSharp/API/Exchanges/BitBank/ExchangeBitBankAPI.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ protected override async Task<ExchangeOrderResult> OnPlaceOrderAsync(ExchangeOrd
129129
if (order.OrderType == OrderType.Stop)
130130
throw new InvalidOperationException("Bitbank does not support stop order");
131131
Dictionary<string, object> payload = await GetNoncePayloadAsync();
132+
if (order.IsPostOnly != null)
133+
payload["post_only"] = order.IsPostOnly;
132134
payload.Add("pair", NormalizeMarketSymbol(order.MarketSymbol));
133135
payload.Add("amount", order.Amount.ToStringInvariant());
134136
payload.Add("side", order.IsBuy ? "buy" : "sell");

src/ExchangeSharp/API/Exchanges/BitMEX/ExchangeBitMEXAPI.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -693,10 +693,10 @@ private void AddOrderToPayload(ExchangeOrderRequest order, Dictionary<string, ob
693693
if(order.OrderType!=OrderType.Market)
694694
payload["price"] = order.Price;
695695

696-
if (order.ExtraParameters.TryGetValue("execInst", out var execInst))
697-
{
698-
payload["execInst"] = execInst;
699-
}
696+
if (order.IsPostOnly == true)
697+
payload["execInst"] = "ParticipateDoNotInitiate"; // Also known as a Post-Only order. If this order would have executed on placement, it will cancel instead. This is intended to protect you from the far touch moving towards you while the order is in transit. It is not intended for speculating on the far touch moving away after submission - we consider such behaviour abusive and monitor for it.
698+
699+
order.ExtraParameters.CopyTo(payload);
700700
}
701701

702702
private ExchangePosition ParsePosition(JToken token)

src/ExchangeSharp/API/Exchanges/Bitfinex/ExchangeBitfinexAPI.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,7 @@ protected override async Task<ExchangeOrderResult> OnPlaceOrderAsync(ExchangeOrd
488488
{
489489
payload["price"] = "1";
490490
}
491+
if (order.IsPostOnly == true) payload["flags"] = "4096"; // The post-only limit order option ensures the limit order will be added to the order book and not match with a pre-existing order unless the pre-existing order is a hidden order.
491492
order.ExtraParameters.CopyTo(payload);
492493
JToken obj = await MakeJsonRequestAsync<JToken>("/order/new", BaseUrlV1, payload);
493494
return ParseOrder(obj);

src/ExchangeSharp/API/Exchanges/Bitstamp/ExchangeBitstampAPI.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,8 @@ private static Dictionary<string, decimal> ExtractDictionary(JObject responseObj
195195

196196
protected override async Task<ExchangeOrderResult> OnPlaceOrderAsync(ExchangeOrderRequest order)
197197
{
198-
string action = order.IsBuy ? "buy" : "sell";
198+
if (order.IsPostOnly != null) throw new NotImplementedException("Post Only orders are not supported by this exchange or not implemented in ExchangeSharp. Please submit a PR if you are interested in this feature.");
199+
string action = order.IsBuy ? "buy" : "sell";
199200
string market = order.OrderType == OrderType.Market ? "/market" : "";
200201
string url = $"/{action}{market}/{order.MarketSymbol}/";
201202
Dictionary<string, object> payload = await GetNoncePayloadAsync();

src/ExchangeSharp/API/Exchanges/Bittrex/ExchangeBittrexAPI.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,8 @@ protected override async Task<ExchangeOrderResult> OnPlaceOrderAsync(ExchangeOrd
389389
if (order.OrderType == ExchangeSharp.OrderType.Limit)
390390
{
391391
orderParams.Add("limit", orderPrice);
392-
orderParams.Add("timeInForce", "GOOD_TIL_CANCELLED");
392+
if (order.IsPostOnly == true) orderParams.Add("timeInForce", "POST_ONLY_GOOD_TIL_CANCELLED"); // This option allows market makers to ensure that their orders are making it to the order book instead of matching with a pre-existing order. Note: If the order is not a maker order, you will return an error and the order will be cancelled
393+
else orderParams.Add("timeInForce", "GOOD_TIL_CANCELLED");
393394
}
394395

395396
foreach (KeyValuePair<string, object> kv in order.ExtraParameters)

src/ExchangeSharp/API/Exchanges/Bybit/ExchangeBybitAPI.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,7 @@ protected override async Task<ExchangeOrderResult> OnPlaceOrderAsync(ExchangeOrd
816816

817817
public async Task<ExchangeOrderResult> OnAmendOrderAsync(ExchangeOrderRequest order)
818818
{
819+
if (order.IsPostOnly != null) throw new NotImplementedException("Post Only orders are not supported by this exchange or not implemented in ExchangeSharp. Please submit a PR if you are interested in this feature.");
819820
var payload = new Dictionary<string, object>();
820821
payload["symbol"] = order.MarketSymbol;
821822
if(order.OrderId != null)

0 commit comments

Comments
 (0)