package br.com.kronus.ibkr.futures;
import java.math.BigDecimal;
import java.time.Duration;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import com.ib.client.Contract;
import com.ib.client.Decimal;
import com.ib.client.Order;
import br.com.kronus.core.StatusOrdemFuturos;
import br.com.kronus.core.trade.ServicoOrdensFuturos;
import br.com.kronus.ibkr.api.IbkrClient;
import br.com.kronus.ibkr.api.IbkrMapper;
/**
* Implementação de ordens usando IBKR, mantendo a assinatura da Binance.
*/
public class ServicoOrdensFuturosIbkr
implements ServicoOrdensFuturos
{
private final IbkrClient ibkr
;
private final Map<String,
Integer> mapaClientOrder =
new ConcurrentHashMap<>();
public ServicoOrdensFuturosIbkr
(IbkrClient ibkr
) {
super();
this.
ibkr = ibkr
;
}
@
Override
public StatusOrdemFuturos novaOrdemLimit
(
String symbol,
String side,
BigDecimal quantity,
BigDecimal price,
String clientOrderId
) throws Exception {
int orderId = ibkr.
getNextOrderIdBlocking(Duration.
ofSeconds(5));
Contract contract = IbkrMapper.
contratoFuturoIndice(symbol
);
Order order =
new Order
();
order.
action(side
);
order.
orderType("LMT");
order.
totalQuantity(Decimal.
get(quantity
));
order.
lmtPrice(price.
doubleValue());
order.
tif("GTC");
order.
orderRef(clientOrderId
);
mapaClientOrder.
put(clientOrderId, orderId
);
CompletableFuture
<StatusOrdemFuturos
> future = ibkr.
registrarFutureOrdem(orderId
);
System.
out.
println("[IBKR-ORDEM] Enviando ordem: id=" + orderId +
", symbol=" + contract.
symbol() +
", localSymbol=" + contract.
localSymbol() +
", secType=" + contract.
getSecType() +
", exchange=" + contract.
exchange() +
", primaryExch=" + contract.
primaryExch() +
", currency=" + contract.
currency());
ibkr.
getClient().
placeOrder(orderId, contract, order
);
StatusOrdemFuturos status = future.
get(10,
TimeUnit.
SECONDS);
status.
setClientOrderId(clientOrderId
);
status.
setSymbol(symbol
);
return status
;
}
@
Override
public StatusOrdemFuturos consultarStatusOrdem
(String symbol,
String origClientOrderId
) throws Exception {
Integer orderId = mapaClientOrder.
get(origClientOrderId
);
if (orderId ==
null) {
throw new IllegalArgumentException("Não há orderId mapeado para clientOrderId=" + origClientOrderId
);
}
CompletableFuture
<StatusOrdemFuturos
> future = ibkr.
registrarFutureOrdem(orderId
);
ibkr.
getClient().
reqOpenOrders();
StatusOrdemFuturos status = future.
get(5,
TimeUnit.
SECONDS);
status.
setClientOrderId(origClientOrderId
);
status.
setSymbol(symbol
);
return status
;
}
}