> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qfex.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 标的资产价格

QFEX 提供汇总多个交易所行情的**定时标的价格数据流**，用于永续市场的**资金费用计算**。

> [!NOTE]
>
> 在延长交易时段以外，返回的标的价格会包含 `source: internal`。预言机详情见[预言机定价](https://docs.qfex.com/cn/qfex/contract-specifications.md#oracle-pricing)，资金费用时段行为见[资金费率](https://docs.qfex.com/cn/qfex/funding.md)。

## 使用方式

连接公开 WebSocket：

* URL：`wss://mds.qfex.com`。

然后发送订阅消息：

```json theme={null}
{"type": "subscribe","channels": ["underlier"],"symbols": ["AAPL-USD","US500-USD"]}
```

## 示例代码

```python python theme={null}
# Python (websocket-client)
# pip install websocket-client
import json
import websocket

def on_open(ws):
    sub = {
        "type": "subscribe",
        "channels": ["underlier"],
        "symbols": ["US500-USD"]  # or ["*"]
    }
    ws.send(json.dumps(sub))

def on_message(ws, message):
    data = json.loads(message)
    print("Underlier update:", json.dumps(data, indent=2))

def on_error(ws, error):
    print("Error:", error)

def on_close(ws, close_status_code, close_msg):
    print("Closed:", close_status_code, close_msg)

if __name__ == "__main__":
    ws = websocket.WebSocketApp(
        "wss://mds.qfex.com",
        on_open=on_open,
        on_message=on_message,
        on_error=on_error,
        on_close=on_close,
    )
    ws.run_forever()
```

```javascript node theme={null}
// Node.js (ws)
// npm i ws
import WebSocket from "ws";

const ws = new WebSocket("wss://mds.qfex.com");

ws.on("open", () => {
  const sub = {
    type: "subscribe",
    channels: ["underlier"],
    symbols: ["US500-USD"], // or ["*"]
  };
  ws.send(JSON.stringify(sub));
});

ws.on("message", (msg) => {
  try {
    const data = JSON.parse(msg.toString());
    console.log("Underlier update:", data);
  } catch (e) {
    console.error("Parse error:", e);
  }
});

ws.on("error", (err) => console.error("WS error:", err));
ws.on("close", (code, reason) => console.log("Closed:", code, reason?.toString()));
```

```go go theme={null}
// Go (gorilla/websocket)
// go get github.com/gorilla/websocket
package main

import (
	"fmt"
	"log"
	"os"
	"os/signal"

	"github.com/gorilla/websocket"
)

func main() {
	c, _, err := websocket.DefaultDialer.Dial("wss://mds.qfex.com", nil)
	if err != nil {
		log.Fatal("dial:", err)
	}
	defer c.Close()

	sub := map[string]interface{}{
		"type":     "subscribe",
		"channels": []string{"underlier"},
		"symbols":  []string{"US500-USD"}, // or []string{"*"}
	}
	if err := c.WriteJSON(sub); err != nil {
		log.Fatal("write:", err)
	}

	done := make(chan struct{})
	go func() {
		defer close(done)
		for {
			_, message, err := c.ReadMessage()
			if err != nil {
				log.Println("read:", err)
				return
			}
			fmt.Printf("Underlier update: %s\n", message)
		}
	}()

	// keep running until Ctrl+C
	interrupt := make(chan os.Signal, 1)
	signal.Notify(interrupt, os.Interrupt)
	<-interrupt
}
```

```java java theme={null}
// Java (OkHttp WebSocket)
// Gradle: implementation("com.squareup.okhttp3:okhttp:4.12.0")
import java.util.concurrent.TimeUnit;
import okhttp3.*;

public class UnderlierWs {
  public static void main(String[] args) {
    OkHttpClient client = new OkHttpClient.Builder()
        .pingInterval(20, TimeUnit.SECONDS)
        .build();

    Request request = new Request.Builder()
        .url("wss://mds.qfex.com")
        .build();

    WebSocketListener listener = new WebSocketListener() {
      @Override public void onOpen(WebSocket webSocket, Response response) {
        String sub = "{\"type\":\"subscribe\",\"channels\":[\"underlier\"],\"symbols\":[\"US500-USD\"]}";
        webSocket.send(sub);
      }
      @Override public void onMessage(WebSocket webSocket, String text) {
        System.out.println("Underlier update: " + text);
      }
      @Override public void onFailure(WebSocket webSocket, Throwable t, Response response) {
        System.err.println("WS error: " + t.getMessage());
      }
    };

    client.newWebSocket(request, listener);

    // Keep JVM alive
    try { Thread.sleep(Long.MAX_VALUE); } catch (InterruptedException ignored) {}
  }
}
```

## 响应示例

```json theme={null}
{
  "type": "underlier",
  "sequence": 50,
  "time": "2014-11-07T08:19:27.028459Z",
  "symbol": "AAPL-USD",
  "price": "400.23",
  "source": "external"
}
```

### 取消订阅（可选）

```json theme={null}
{"type":"unsubscribe","channels":["underlier"],"symbols":["US500-USD"]}
```

## 注意事项

* 定时推送汇总多个交易所的价格。
* 用于计算资金费率。
* 延长交易时段以外，价格可能继续更新，并标记为 `source: internal`。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.