You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

发送Logon时Deribit FIX连接中断问题(基于QuickFIX)

排查Deribit FIX接口QuickFIX连接中断问题

问题背景

基于QuickFIX开发Deribit FIX行情数据获取项目,已确认API凭证有效且具备读写权限,但发送Logon消息后立即出现连接中断:

2025-12-04 00:42:48,691 - INFO -  Sending Logon with Deribit authentication
2025-12-04 00:42:48,743 - INFO - connection stops on this idFIX.4.4:MYTRADER->DERIBITSERVER

相关登录逻辑代码如下:

def toAdmin(self, message, sessionID):
    """Handles message authentication for outgoing admin messages."""
    msg_type = fix.MsgType()
    message.getHeader().getField(msg_type)

    if msg_type.getValue() == fix.MsgType_Logon:
        nonce = os.urandom(32)
        timestamp_ms = str(int(time.time() * 1000))
        nonce_b64 = base64.b64encode(nonce).decode('utf-8')
        raw_data = f"{timestamp_ms}.{nonce_b64}"

        signature_input = raw_data + self.client_secret
        signature_hash = hashlib.sha256(signature_input.encode('utf-8')).digest()
        signature_b64 = base64.b64encode(signature_hash).decode('utf-8')

        message.setField(fix.Username(self.client_id))        # tag 553
        message.setField(fix.Password(signature_b64))         # tag 554
        message.setField(fix.RawDataLength(len(raw_data)))    # tag 95
        message.setField(fix.RawData(raw_data))               # tag 96

        logger.info("Sending Logon with Deribit authentication")
        logger.info(f"Client ID: {self.client_id}")
        logger.info(f"Client Secret (first 10): {self.client_secret[:10]}...")
        logger.info(f"Timestamp: {timestamp_ms}")
        logger.info(f"RawData length: {len(raw_data)}")
        logger.info(f"RawData: {raw_data}")
        logger.info(f"Signature (first 20): {signature_b64[:20]}...")
        logger.info(f"Full Logon Message:\n{message.toString()}")

def fromAdmin(self, message, sessionID):
    """Handles incoming admin messages from Deribit."""
    msg_type = fix.MsgType()
    message.getHeader().getField(msg_type)

    logger.info(f"Received admin message type: {msg_type.getValue()}")
    logger.info(f"Full message:\n{message.toString()}")

    if msg_type.getValue() == fix.MsgType_Logon:
        logger.info("Logon acknowledgment received from Deribit!")

    elif msg_type.getValue() == fix.MsgType_Logout:
        text = fix.Text()
        if message.isSetField(text):
            message.getField(text)
            logger.error(f"LOGOUT RECEIVED - Reason: {text.getValue()}")
        else:
            logger.error("LOGOUT RECEIVED - No reason provided")
        logger.error(f"Full logout message:\n{message.toString()}")

    elif msg_type.getValue() == fix.MsgType_Reject:
        logger.error(f"REJECT RECEIVED:\n{message.toString()}")
        if message.isSetField(fix.Text()):
            text = fix.Text()
            message.getField(text)
            logger.error(f"Reject reason: {text.getValue()}")

    else:
        logger.debug(f"Admin message type: {msg_type.getValue()}")

def toApp(self, message, sessionID):
    """Handles outgoing application messages."""
    logger.debug(f"Sending message to app: {message}")

def fromApp(self, message, sessionID):
    """Handles incoming application messages."""
    try:
        self.process_message(message, sessionID)
    except Exception as e:
        logger.error(f"Error processing message: {e}", exc_info=True)

排查与修复方案

1. 检查Deribit FIX端点与SSL配置

Deribit测试网和主网的FIX端点不同,且强制使用SSL加密:

  • 测试网:fix.test.deribit.com:443
  • 主网:fix.deribit.com:443
    确保QuickFIX配置文件中SocketConnectHost、SocketConnectPort正确,且添加UseSSL=Y启用传输层加密。

2. 补全Logon消息必填字段

Deribit要求Logon消息必须包含以下字段,当前代码可能遗漏:

  • EncryptMethod (tag 98):固定为0(Deribit用SSL加密,无需应用层加密)
  • HeartBtInt (tag 108):建议设为30(心跳间隔,单位秒)
  • ResetSeqNumFlag (tag 141):设为Y重置会话序列号,避免历史序列冲突

修改toAdmin方法,在设置现有字段后添加:

message.setField(fix.EncryptMethod(0))
message.setField(fix.HeartBtInt(30))
message.setField(fix.ResetSeqNumFlag(True))

3. 校准本地服务器时间

Deribit的签名验证依赖精确时间戳,要求本地时间与NTP服务器同步,误差不能超过5分钟。使用系统自带时间同步工具或ntpdate命令校准时间。

4. 开启QuickFIX详细日志

修改QuickFIX配置文件,开启调试级日志,查看底层交互细节:

FileStorePath=store
FileLogPath=log
UseDataDictionary=Y
DataDictionary=FIX44.xml
SocketConnectHost=fix.test.deribit.com
SocketConnectPort=443
UseSSL=Y
LogonTimeout=30
HeartBtInt=30
ResetSeqNumFlag=Y
# 开启调试日志
Debug=Y
LogMessages=Y

查看log目录下的日志文件,确认是否收到Deribit返回的Reject/Logout消息(可能因日志级别未在终端输出)。

5. 验证签名生成逻辑

对照Deribit规则检查签名生成:

  1. nonce必须是32字节随机数据,Base64编码后无多余字符
  2. 时间戳必须是毫秒级字符串
  3. 签名输入为{timestamp_ms}.{nonce_b64} + client_secret,无额外分隔符
  4. SHA256哈希后需Base64编码作为Password字段

6. 检查会话ID配置

Deribit的FIX会话ID格式为FIX.4.4:CLIENT_ID->DERIBIT,确保配置文件中SenderCompID为你的Client ID,TargetCompID为DERIBIT(测试网/主网一致)。

总结

优先排查SSL配置、必填字段完整性和时间同步,这些是Deribit FIX连接中断的高频原因。开启详细日志后,可精准定位Deribit返回的具体错误信息。

内容的提问来源于stack exchange,提问作者AKSHAT GUPTA

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 22:47:03