Skip to content

程序员常用的IDEA插件:https://github.com/silently9527/Toolkit

微信公众号:贝塔学Java

前提

  • 本文使用的交易所SDK是 ExchangeSDK
  • 本文所有内容仅用于讨论,没有任何交易建议,不对任何交易行为负责

永续合约

在开始分享套利策略之前,需要先来了解一些合约的概念。 永续合约是一种没有到期日的衍生品合约形式,广泛应用于加密货币和其他金融市场。与传统的期货合约不同,永续合约没有预定的交割日期,因此交易者可以无限期持有该合约。 永续合约的设计目的是为了模拟现货市场,但允许使用杠杆和做空。

永续合约的特点:

  • 没有到期日:永续合约没有到期时间,交易者可以根据需要持有合约,直到选择平仓。
  • 杠杆交易:交易者可以利用杠杆进行永续合约交易,即用较少的资金控制更大规模的头寸。
  • 双向交易:永续合约允许交易者做多或做空标的资产。做多即买入合约,预期标的资产价格上涨;做空则是卖出合约,预期标的资产价格下跌。

这里可以考虑下,由于永续合约没有到期时间,不同于交割合约到期后会有个交割价格,这就导致了永续合约的价格可能会远远的偏离现货的价格,为了解决这个问题就引入了资金费率

资金费率

合约市场中的资金费率是永续合约中的一个重要机制,主要用于保证合约价格与现货市场价格的接近。如何保证的呢?

  • 当合约市场价格高于现货市场价格时,资金费率为正。此时,做多的交易者需要支付资金费率给做空的交易者。
  • 当合约市场价格低于现货市场价格时,资金费率为负。此时,做空的交易者需要支付资金费率给做多的交易者。

通过收取资金费用来保证合约市场的价格尽量与现货市场价格接近,通常每隔8小时进行一次资金费用结算。

套利策略的思路

  1. 监控市场所有合约的资金费率,找出市场中资金费率最大
  2. 采用高倍杠杆在资金费用开始结算前几秒使用脚本开仓
  3. 等待资金费用结算完成后立即平仓(越快越好,所以需要服务器网速快)

查询资金费率

  1. 这里只展示KC的资金费率查询,其他交易所类似
  2. 查询出所有的永续合约,再去遍历查询合约的资金费率,然后排序取出资金费率前5的合约信息(这里用到的交易所接口都封装到了ExchangeSDK)
java
FutureRestApiClient restApiClient = FutureApiInternalFactory.getInstance()
                .createKucoinFutureRestApiClient(Constants.Future.KUCOIN_REST_API_BASE_URL, "your appKey", "your appSecret", "your passphrase");
List<FundingRate> fundingRateList = restApiClient.getFutures()
        .stream()
        .filter(future -> "USDT".equals(future.getQuoteAsset()) && future.getFutureType().equals(FutureType.PERPETUAL))
        .map(future -> {
            Utils.sleep(500);
            return restApiClient.getFundingRate(future.getSymbol());
        })
        .sorted(sortFundingRate())
        .limit(5)
        .collect(toList());

String message = fundingRateList
        .stream()
        .map(fundingRate -> String.format("SYMBOL: %s, FundingRate: %s", fundingRate.getSymbol(), fundingRate.getFundingRate()))
        .collect(Collectors.joining("\n"));
log.info("current FundingRate: {}", message);

由于资金费率可能为正,也可能为负,所以我们在排序的时候需要使用绝对值比较

java
private Comparator<FundingRate> sortFundingRate() {
    return (o1, o2) -> {
        int compare = o1.getFundingRate().abs().compareTo(o2.getFundingRate().abs());
        if (compare > 0) {
            return -1;
        } else if (compare < 0) {
            return 1;
        }
        return 0;
    };
}

套利程序

设计套利程序的参数

  • symbol: 设置需要套利的交易对;在上面我们已经查询出来了最大的资金费率,通过会在前5进行选择
  • money: 设置需要套利的本金;
  • openSide: 设置开仓方向;资金费率为正,就去卖;资金费率为负,就去买
  • leverage: 设置开仓杠杆(通常是逐仓使用,全仓使用的全局杠杆)
java
public void start() throws Exception {
    Future future = this.restApiClient.getFuture(this.symbol);
    SymbolPrice ticker = this.restApiClient.getSymbolPriceTicker(this.symbol);
    BigDecimal tradeAmount = this.money.multiply(new BigDecimal(this.leverage))
            .divide(ticker.getPrice(), 10, RoundingMode.DOWN)
            .divide(future.getMultiplier(), 0, RoundingMode.DOWN);
    log.info("current market price:{}, tradeAmount:{}", ticker.getPrice(), tradeAmount);
    if (tradeAmount.doubleValue() <= 0) {
        return;
    }

    this.restApiClient.postOrder(symbol, openSide, PositionSide.BOTH, OrderType.MARKET, TimeInForce.GTC, tradeAmount, ticker.getPrice(), false, Utils.uuid(), null, null, leverage);

    Utils.sleep(200);

    this.restApiClient.postOrder(symbol, openSide.oppositeSide(), PositionSide.BOTH, OrderType.MARKET, TimeInForce.GTC, tradeAmount, ticker.getPrice(), false, Utils.uuid(), null, null, leverage);
    log.info("FutureQuickInOutPolicy Finish");
}

由于开仓和平仓都是使用的市价单,所以该策略很依赖盘口深度,如果深度太差会导致滑点很大

若需完整源码加微信silently9527,免费分享

最后(看完不点关注,你们想白嫖我吗)

文中或许会存在或多或少的不足、错误之处,有建议或者意见也非常欢迎大家在评论交流。

最后,写作不易,请不要白嫖我哟,希望朋友们可以点赞评论关注三连,因为这些就是我分享的全部动力来源🙏