Skip to content

Commit

Permalink
Merge branch 'develop' into okx_implement_channel_inactive_listener
Browse files Browse the repository at this point in the history
  • Loading branch information
rizer1980 committed Jun 23, 2023
2 parents b0f012b + 3b771db commit 6503a35
Show file tree
Hide file tree
Showing 62 changed files with 1,593 additions and 182 deletions.
4 changes: 2 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright 2015-2021 Knowm Inc. (http://knowm.org) and contributors.
Copyright 2015-2023 Knowm Inc. (http://knowm.org) and contributors.
Copyright 2012-2015 Xeiam LLC (http://xeiam.com) and contributors.

Permission is hereby granted, free of charge, to any person obtaining a copy
Expand All @@ -19,4 +19,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
THE SOFTWARE.
9 changes: 8 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@
<module>xchange-stream-hitbtc</module>
<module>xchange-stream-huobi</module>
<module>xchange-stream-kraken</module>
<module>xchange-stream-kucoin</module>
<module>xchange-stream-lgo</module>
<module>xchange-stream-okcoin</module>
<module>xchange-stream-okex</module>
Expand Down Expand Up @@ -247,7 +248,13 @@

<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-all</artifactId>
<artifactId>resilience4j-ratelimiter</artifactId>
<version>${version.resilience4j}</version>
</dependency>

<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-retry</artifactId>
<version>${version.resilience4j}</version>
</dependency>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public enum OrderType {
STOP,
TAKE_PROFIT,
TAKE_PROFIT_MARKET,
TRAILING_STOP_MARKET,
LIMIT_MAKER;

@JsonCreator
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package org.knowm.xchange.binance.dto.trade;

import org.knowm.xchange.dto.Order.IOrderFlags;

/**
* @see <a
* href="https://github.com/binance/binance-spot-api-docs/blob/master/faqs/trailing-stop-faq.md">trailing-stop-faq</a>
* @author mrmx
*/
public enum TrailingFlag implements IOrderFlags {
/** Trailing of 0.01% */
P0_01(1),
/** Trailing of 0.1% */
P0_1(10),
/** Trailing of 1% */
P1(100),
/** Trailing of 10% */
P10(1000);
/** Basis Points, also known as BIP or BIPS, are used to indicate a percentage change. */
private final long trailingBip;

private TrailingFlag(long trailingBip) {
this.trailingBip = trailingBip;
}

public long getTrailingBip() {
return trailingBip;
}

static TrailingFlag of(Number percent) {
switch (percent.toString()) {
case "0.01":
return P0_01;
case "0.1":
return P0_1;
case "1":
return P1;
case "10":
return P10;
}
throw new IllegalArgumentException("Invalid trailing " + percent);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import lombok.Value;
import org.knowm.xchange.binance.BinanceAdapters;
import org.knowm.xchange.binance.BinanceErrorAdapter;
Expand Down Expand Up @@ -35,9 +34,7 @@

public class BinanceTradeService extends BinanceTradeServiceRaw implements TradeService {

public BinanceTradeService(
BinanceExchange exchange,
ResilienceRegistries resilienceRegistries) {
public BinanceTradeService(BinanceExchange exchange, ResilienceRegistries resilienceRegistries) {
super(exchange, resilienceRegistries);
}

Expand All @@ -54,13 +51,14 @@ public OpenOrders getOpenOrders(CurrencyPair pair) throws IOException {
public OpenOrders getOpenOrders(OpenOrdersParams params) throws IOException {
try {
Instrument pair = null;
if(params instanceof OpenOrdersParamInstrument){
if (params instanceof OpenOrdersParamInstrument) {
pair = ((OpenOrdersParamInstrument) params).getInstrument();
} else if(params instanceof OpenOrdersParamCurrencyPair){
} else if (params instanceof OpenOrdersParamCurrencyPair) {
pair = ((OpenOrdersParamCurrencyPair) params).getCurrencyPair();
}

return BinanceAdapters.adaptOpenOrders(openOrdersAllProducts(pair), pair instanceof FuturesContract);
return BinanceAdapters.adaptOpenOrders(
openOrdersAllProducts(pair), pair instanceof FuturesContract);

} catch (BinanceException e) {
throw BinanceErrorAdapter.adapt(e);
Expand All @@ -69,20 +67,21 @@ public OpenOrders getOpenOrders(OpenOrdersParams params) throws IOException {

@Override
public String placeMarketOrder(MarketOrder mo) throws IOException {
return placeOrderAllProducts(OrderType.MARKET, mo, null, null, null, null, null,null);
return placeOrderAllProducts(OrderType.MARKET, mo, null, null, null, null, null, null);
}

@Override
public String placeLimitOrder(LimitOrder limitOrder) throws IOException {
TimeInForce tif = timeInForceFromOrder(limitOrder).orElse(TimeInForce.GTC);
TimeInForce tif = getOrderFlag(limitOrder, TimeInForce.class).orElse(TimeInForce.GTC);
OrderType type;
if (limitOrder.hasFlag(org.knowm.xchange.binance.dto.trade.BinanceOrderFlags.LIMIT_MAKER)) {
type = OrderType.LIMIT_MAKER;
tif = null;
} else {
type = OrderType.LIMIT;
}
return placeOrderAllProducts(type, limitOrder, limitOrder.getLimitPrice(), null, null, null,null, tif);
return placeOrderAllProducts(
type, limitOrder, limitOrder.getLimitPrice(), null, null, null, null, tif);
}

@Override
Expand All @@ -93,18 +92,26 @@ public String placeStopOrder(StopOrder order) throws IOException {
// allow
// it at some point.
TimeInForce tif =
timeInForceFromOrder(order).orElse(order.getLimitPrice() != null ? TimeInForce.GTC : null);

getOrderFlag(order, TimeInForce.class)
.orElse(order.getLimitPrice() != null ? TimeInForce.GTC : null);
Long trailingDelta =
getOrderFlag(order, TrailingFlag.class).map(TrailingFlag::getTrailingBip).orElse(null);
OrderType orderType = BinanceAdapters.adaptOrderType(order);

return placeOrderAllProducts(
orderType, order, order.getLimitPrice(), order.getStopPrice(), null, null, order.getTrailValue(), tif);
orderType,
order,
order.getLimitPrice(),
order.getStopPrice(),
null,
trailingDelta,
order.getTrailValue(),
tif);
}

private Optional<TimeInForce> timeInForceFromOrder(Order order) {
return order.getOrderFlags().stream()
.filter(flag -> flag instanceof TimeInForce)
.map(flag -> (TimeInForce) flag)
private <T extends IOrderFlags> Optional<T> getOrderFlag(Order order, Class<T> clazz) {
return (Optional<T>) order.getOrderFlags().stream()
.filter(flag -> clazz.isAssignableFrom(flag.getClass()))
.findFirst();
}

Expand All @@ -121,36 +128,41 @@ private String placeOrderAllProducts(
try {
String orderId;

if(order.getInstrument() instanceof FuturesContract){
orderId = newFutureOrder(
order.getInstrument(),
BinanceAdapters.convert(order.getType()),
type,
tif,
order.getOriginalAmount(),
order.hasFlag(org.knowm.xchange.binance.dto.trade.BinanceOrderFlags.REDUCE_ONLY),
limitPrice,
getClientOrderId(order),
stopPrice,
false,
null,
callBackRate,
null
).getOrderId();
if (order.getInstrument() instanceof FuturesContract) {
orderId =
newFutureOrder(
order.getInstrument(),
BinanceAdapters.convert(order.getType()),
type,
tif,
order.getOriginalAmount(),
order.hasFlag(
org.knowm.xchange.binance.dto.trade.BinanceOrderFlags.REDUCE_ONLY),
limitPrice,
getClientOrderId(order),
stopPrice,
false,
null,
callBackRate,
null)
.getOrderId();
} else {
orderId = Long.toString(newOrder(
order.getInstrument(),
BinanceAdapters.convert(order.getType()),
type,
tif,
order.getOriginalAmount(),
quoteOrderQty, // TODO (BigDecimal)order.getExtraValue("quoteOrderQty")
limitPrice,
getClientOrderId(order),
stopPrice,
trailingDelta, // TODO (Long)order.getExtraValue("trailingDelta")
null,
null).orderId);
orderId =
Long.toString(
newOrder(
order.getInstrument(),
BinanceAdapters.convert(order.getType()),
type,
tif,
order.getOriginalAmount(),
quoteOrderQty,
limitPrice,
getClientOrderId(order),
stopPrice,
trailingDelta,
null,
null)
.orderId);
}
return orderId;
} catch (BinanceException e) {
Expand All @@ -172,7 +184,7 @@ public void placeTestOrder(
Long trailingDelta)
throws IOException {
try {
TimeInForce tif = timeInForceFromOrder(order).orElse(null);
TimeInForce tif = getOrderFlag(order, TimeInForce.class).orElse(null);
testNewOrder(
order.getInstrument(),
BinanceAdapters.convert(order.getType()),
Expand Down Expand Up @@ -216,10 +228,7 @@ public boolean cancelOrder(CancelOrderParams params) throws IOException {
CancelOrderByInstrument paramInstrument = (CancelOrderByInstrument) params;
CancelOrderByIdParams paramId = (CancelOrderByIdParams) params;
cancelOrderAllProducts(
paramInstrument.getInstrument(),
BinanceAdapters.id(paramId.getOrderId()),
null,
null);
paramInstrument.getInstrument(), BinanceAdapters.id(paramId.getOrderId()), null, null);

return true;
} catch (BinanceException e) {
Expand All @@ -246,8 +255,7 @@ public UserTrades getTradeHistory(TradeHistoryParams params) throws IOException
TradeHistoryParamInstrument pairParams = (TradeHistoryParamInstrument) params;
Instrument pair = pairParams.getInstrument();
if (pair == null) {
throw new ExchangeException(
"You need to provide the instrument to get the user trades.");
throw new ExchangeException("You need to provide the instrument to get the user trades.");
}
Long orderId = null;
Long startTime = null;
Expand Down Expand Up @@ -279,7 +287,8 @@ public UserTrades getTradeHistory(TradeHistoryParams params) throws IOException
limit = limitParams.getLimit();
}

List<BinanceTrade> binanceTrades = myTradesAllProducts(pair, orderId, startTime, endTime, fromId, limit);
List<BinanceTrade> binanceTrades =
myTradesAllProducts(pair, orderId, startTime, endTime, fromId, limit);

return BinanceAdapters.adaptUserTrades(binanceTrades, pair instanceof FuturesContract);
} catch (BinanceException e) {
Expand All @@ -294,22 +303,22 @@ public Collection<Order> getOrder(OrderQueryParams... params) throws IOException
for (OrderQueryParams param : params) {
if (!(param instanceof OrderQueryParamInstrument)) {
throw new ExchangeException(
"Parameters must be an instance of OrderQueryParamInstrument");
"Parameters must be an instance of OrderQueryParamInstrument");
}
OrderQueryParamInstrument orderQueryParamInstrument =
(OrderQueryParamInstrument) param;
OrderQueryParamInstrument orderQueryParamInstrument = (OrderQueryParamInstrument) param;
if (orderQueryParamInstrument.getInstrument() == null
|| orderQueryParamInstrument.getOrderId() == null) {
|| orderQueryParamInstrument.getOrderId() == null) {
throw new ExchangeException(
"You need to provide the currency pair and the order id to query an order.");
"You need to provide the currency pair and the order id to query an order.");
}

orders.add(
BinanceAdapters.adaptOrder(
orderStatusAllProducts(
orderQueryParamInstrument.getInstrument(),
BinanceAdapters.id(orderQueryParamInstrument.getOrderId()),
null), orderQueryParamInstrument.getInstrument() instanceof FuturesContract));
BinanceAdapters.adaptOrder(
orderStatusAllProducts(
orderQueryParamInstrument.getInstrument(),
BinanceAdapters.id(orderQueryParamInstrument.getOrderId()),
null),
orderQueryParamInstrument.getInstrument() instanceof FuturesContract));
}
return orders;
} catch (BinanceException e) {
Expand All @@ -325,16 +334,16 @@ public OpenPositions getOpenPositions() throws IOException {
@Override
public Collection<String> cancelAllOrders(CancelAllOrders orderParams) throws IOException {

if(!(orderParams instanceof CancelOrderByInstrument)){
throw new NotAvailableFromExchangeException("Parameters must be an instance of "+CancelOrderByInstrument.class.getSimpleName());
if (!(orderParams instanceof CancelOrderByInstrument)) {
throw new NotAvailableFromExchangeException(
"Parameters must be an instance of " + CancelOrderByInstrument.class.getSimpleName());
}

Instrument instrument = ((CancelOrderByInstrument) orderParams).getInstrument();

return cancelAllOpenOrdersAllProducts(instrument)
.stream()
.map(binanceCancelledOrder -> Long.toString(binanceCancelledOrder.orderId))
.collect(Collectors.toList());
return cancelAllOpenOrdersAllProducts(instrument).stream()
.map(binanceCancelledOrder -> Long.toString(binanceCancelledOrder.orderId))
.collect(Collectors.toList());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.knowm.xchange.binance.dto.trade;

import java.util.Arrays;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchIllegalArgumentException;
import org.junit.Test;

/** @author mrmx */
public class TrailingFlagTest {

/** Test of method, of class BinanceOrderTrailingFlag. */
@Test
public void testOfValue() {
System.out.println("testOfValue");
List<Number> values = Arrays.asList(0.01, 0.1, 1, 10);
for (Number value : values) {
assertThat(TrailingFlag.of(value).getTrailingBip()).isBetween(1L, 1000L);
}
}

/** Test of method, of class BinanceOrderTrailingFlag. */
@Test
public void testOfValueWithInvalidNumbers() {
System.out.println("testOfValueWithInvalidNumbers");
List<Number> values = Arrays.asList(0.011, 0.11, 2, 11);
for (Number value : values) {
assertThat(
catchIllegalArgumentException(
() -> {
TrailingFlag.of(value);
}))
.as("Invalid value " + value)
.isNotNull();
}
}
}
Loading

0 comments on commit 6503a35

Please sign in to comment.